這次要進行的是一個二進制轉(zhuǎn)換器的開發(fā)狗超,可實現(xiàn)二進制论颅、八進制、十進制镜雨、十六進制的相互轉(zhuǎn)換嫂侍。
本App基于Kotlin語言,Kotlin現(xiàn)在是Google官方推薦的第一安卓開發(fā)語言荚坞,具有簡潔挑宠、可優(yōu)雅避免空指針、完全兼容Java等特點颓影。本項目基于Android Studio 3.0 Canary2各淀。
第一步 新建工程,并選擇Include Kotlin support瞭空,引入Kotlin語言的支持揪阿。
新建項目界面
第二步 選擇界面樣式為Empty Activity后疗我,之后一直下一步咆畏,直到項目創(chuàng)建完成。
選擇Activity樣式
第三步 在build.gradle文件中添加布局拓展吴裤,可以在java文件中直接使用在布局文件中聲明的id的控件旧找,省去findViewById的步驟。
apply plugin: 'kotlin-android-extensions'
第四步 在build.gradle中的dependencies中添加anko麦牺,可以直接在java文件中寫布局钮蛛,省去xml文件鞭缭。
compile "org.jetbrains.anko:anko-sdk15:0.9.1"
第五步 進行主界面設計。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="20dp"
android:orientation="vertical"
tools:context="linchange.example.com.binaryconversion.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<ImageView
android:id="@+id/ivIcon"
android:layout_width="20dp"
android:layout_height="20dp"
android:background="@drawable/ic_info" />
<TextView
android:id="@+id/tvTip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:text="輸入數(shù)字魏颓,自動轉(zhuǎn)換成其他進制"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp">
<TextView
android:layout_width="80dp"
android:layout_height="wrap_content"
android:text=" 二 進 制 "
android:textSize="18sp" />
<EditText
android:id="@+id/etBin"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:layout_weight="1"
android:background="@drawable/edittext_bg"
android:hint="1010"
android:inputType="number"
android:maxLength="28"
android:padding="10dp"
android:singleLine="true" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp">
<TextView
android:layout_width="80dp"
android:layout_height="wrap_content"
android:text=" 八 進 制 "
android:textSize="18sp" />
<EditText
android:id="@+id/etOct"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:layout_weight="1"
android:background="@drawable/edittext_bg"
android:hint="12"
android:inputType="number"
android:maxLength="10"
android:padding="10dp"
android:singleLine="true" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp">
<TextView
android:layout_width="80dp"
android:layout_height="wrap_content"
android:text=" 十 進 制 "
android:textSize="18sp" />
<EditText
android:id="@+id/etDec"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:layout_weight="1"
android:background="@drawable/edittext_bg"
android:hint="10"
android:inputType="number"
android:maxLength="9"
android:padding="10dp"
android:singleLine="true" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp">
<TextView
android:layout_width="80dp"
android:layout_height="wrap_content"
android:text="十六進制"
android:textSize="18sp" />
<EditText
android:id="@+id/etHex"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:layout_weight="1"
android:background="@drawable/edittext_bg"
android:hint="A"
android:inputType="text"
android:maxLength="7"
android:padding="10dp"
android:singleLine="true" />
</LinearLayout>
</LinearLayout>
第六步 進行邏輯代碼的編寫岭辣。
MainActivity.kt
package linchange.example.com.binaryconversion
import android.app.Activity
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.widget.EditText
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_main.*
import org.jetbrains.anko.textChangedListener
class MainActivity : AppCompatActivity() {
enum class TYPE { //進制的類型枚舉
BIN, OCT, DEC, HEX //枚舉分別代表二進制、八進制甸饱、十進制沦童、十六進制
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initEvent(); //初始化事件
}
//初始化事件
private fun initEvent() {
/*
此處的EditText輸入框etBin、etOct叹话、etDec偷遗、etHex由kotlin-android-extensions插件
自動與布局文件activity_main.xml中的id屬性綁定,不用findViewById()
*/
autoSetTextChangeListener(etBin, etOct, etDec, etHex) //批量自動設置EditText的文本改變監(jiān)聽器
}
/**
* 批量自動設置EditText的文本改變監(jiān)聽器
* @param arrayOfEditText EditText的數(shù)組
*/
fun autoSetTextChangeListener(vararg arrayOfEditText: EditText) {
var isRunning: Boolean = false //通過標志位防止afterTextChanged多次執(zhí)行
arrayOfEditText.forEach { editText -> //使用forEach遍歷設置數(shù)組中的EditText
editText.textChangedListener { //給EditText設置文本改變監(jiān)聽器
afterTextChanged { //設置文本改變后調(diào)用的方法
//獲取當前EditText輸入框中的文字驼壶,并設置其他三個輸入框?qū)男畔? str ->
if (!isRunning) { //當未在執(zhí)行
isRunning = true //標志位設為正在執(zhí)行
str.toString().changeNum(getEditType(editText))
isRunning = false //標志位設為執(zhí)行結(jié)束
}
}
}
}
}
/**
* 根據(jù)輸入框獲取輸入的類型
* @param editText 輸入框
* @return 輸入框類型
*/
private fun getEditType(editText: EditText): TYPE
= when (editText.id) {
R.id.etBin -> TYPE.BIN
R.id.etOct -> TYPE.OCT
R.id.etDec -> TYPE.DEC
R.id.etHex -> TYPE.HEX
else -> TYPE.BIN
}
/**
* 設置其他三個輸入框?qū)男畔? * @param type 進制的枚舉類型
*/
fun String.changeNum(type: TYPE) {
val string: String = this //此處的this代表字符串本身
if (string.isEmpty()) { //如果字符串長度為空
setTipIconAndText(R.drawable.ic_info, "輸入數(shù)字,自動轉(zhuǎn)換成其他進制") //設置提示圖標和提示文字
clearAllEditTextContent() //清除所有EditText的文本內(nèi)容
return
}
when (type) { //根據(jù)傳入的類型進行判斷,與java中的switch類似
TYPE.BIN -> { //二進制事件
if (checkValidate(string, TYPE.BIN)) { //檢查字符串是否符合二進制格式
string.setOtherEditTextContent(TYPE.BIN, etOct, etDec, etHex) //批量設置其他的EditText的文本內(nèi)容
} else { //不符合二進制格式
setWrongTipIconAndText("請輸入數(shù)字0或1") //設置錯誤提示圖標和文字
}
}
TYPE.OCT -> { //八進制事件
if (checkValidate(string, TYPE.OCT)) { //檢查字符串是否符合八進制格式
string.setOtherEditTextContent(TYPE.OCT, etBin, etDec, etHex)
} else {
setWrongTipIconAndText("請輸入0到7范圍內(nèi)的數(shù)字") //設置錯誤提示圖標和文字
}
}
TYPE.DEC -> { //十進制事件
if (checkValidate(string, TYPE.DEC)) { //檢查字符串是否符合十進制格式
string.setOtherEditTextContent(TYPE.DEC, etBin, etOct, etHex) //批量設置其他的EditText的文本內(nèi)容
} else {
setWrongTipIconAndText("請輸入數(shù)字0到9") //設置錯誤提示圖標和文字
}
}
TYPE.HEX -> { //十六進制事件
if (checkValidate(string, TYPE.HEX)) { //檢查字符串是否符合十六進制格式
string.setOtherEditTextContent(TYPE.HEX, etBin, etOct, etDec) //批量設置其他的EditText的文本內(nèi)容
} else {
setWrongTipIconAndText("請輸入數(shù)字及A到F") //設置錯誤提示圖標和文字
}
}
else -> {
setWrongTipIconAndText("發(fā)生未知異常") //設置錯誤提示圖標和文字
}
}
}
/**
* 清除所有EditText的文本內(nèi)容
*/
fun clearAllEditTextContent() {
etBin.setText("") //清空二進制輸入框
etOct.setText("") //清空八進制輸入框
etDec.setText("") //清空十進制輸入框
etHex.setText("") //清空十六進制輸入框
}
/**
* 設置錯誤提示圖標和文字
* @param wrongText 錯誤提示文字
*/
fun setWrongTipIconAndText(wrongText: String) {
ivIcon.background = resources.getDrawable(R.drawable.ic_warn) //設置錯誤圖標
tvTip.text = wrongText //設置錯誤提示文字
}
/**
* 設置提示圖標和提示文字
* @param drawableId 圖片的id
* @param tipText 提示文字
*/
fun setTipIconAndText(drawableId: Int, tipText: String) {
ivIcon.background = resources.getDrawable(drawableId) //設置提示圖標
tvTip.text = tipText //設置提示文字
}
/**
* 批量自動設置其他的EditText的文本內(nèi)容
* @param arrayOfEditText EditText的數(shù)組
*/
fun String.setOtherEditTextContent(type: TYPE, vararg arrayOfEditText: EditText) {
val string: String = this //此處的this代表字符串本身
val str: String = when (type) { //將N進制轉(zhuǎn)換成十進制
TYPE.BIN -> Integer.parseInt(string, 2).toString()
TYPE.OCT -> Integer.parseInt(string, 8).toString()
TYPE.DEC -> Integer.parseInt(string, 10).toString()
TYPE.HEX -> Integer.parseInt(string, 16).toString()
}
arrayOfEditText.forEach { editText ->
when (editText.id) { //根據(jù)EditText的id進行判斷铁蹈,進行進制的轉(zhuǎn)換
R.id.etBin -> etBin.setText("" + Integer.toBinaryString(Integer.parseInt(str))) //十進制轉(zhuǎn)二進制
R.id.etOct -> etOct.setText("" + Integer.toOctalString(Integer.parseInt(str))) //十進制轉(zhuǎn)八進制
R.id.etDec -> etDec.setText("" + Integer.parseInt(str)) //十進制轉(zhuǎn)十進制
R.id.etHex -> etHex.setText("" + Integer.toHexString(Integer.parseInt(str)).toUpperCase()) //十進制轉(zhuǎn)十六進制
else -> setWrongTipIconAndText("發(fā)生未知異常") //設置錯誤提示圖標和文字
}
}
//如果進制轉(zhuǎn)換成功排吴,設置提示圖標和提示文字
setTipIconAndText(R.drawable.ic_success, "轉(zhuǎn)換完成")
}
/**
* 檢查字符串是否符合對應進制的標準
* @param str 需要檢查的字符串
* @param type 進制的枚舉類型
* @return 傳入的字符串是否符合對應進制的格式
*/
fun checkValidate(str: String, type: TYPE): Boolean {
when (type) { //根據(jù)傳入的類型進行判斷,與java中的switch類似
TYPE.BIN -> { //二進制事件
val list = listOf<Char>('0','1')
return considerInRange(str, list) //判斷字符串是否完全符合列表規(guī)范
}
TYPE.OCT -> { //八進制事件
val list = listOf<Char>('0','1','2','3','4','5','6','7')
return considerInRange(str, list)
}
TYPE.DEC -> { //十進制事件
val list = listOf<Char>('0','1','2','3','4','5','6','7','8','9')
return considerInRange(str, list)
}
TYPE.HEX -> { //十六進制事件
val list = listOf<Char>('0','1','2','3','4','5','6','7','8',
'9','A','B','C','D','E','F')
return considerInRange(str, list)
}
else -> return false //未知事件般妙,直接返回為假
}
}
/**
* 判斷傳入的字符串是否每個字符都在傳入的列表中存在
* @param str 傳入的字符串
* @param list 參照的字符列表
* @return 是否每個字符都在傳入的列表中存在
*/
fun considerInRange(str: String, list: List<Char>): Boolean {
//將字符串str變成字符數(shù)組涣旨,遍歷該字符數(shù)組
str.toCharArray().forEachIndexed { _, char -> //char是每次遍歷中字符的值
//將字符變成大寫之后判斷是否在參照列表中有存在
if (char.toUpperCase() !in list.toCharArray()) // !in表示不在該列表中
return false //如果字符數(shù)組中有一個不存在參照列表中,該字符串不符合標準
}
return true //全部通過股冗,字符串符合標準
}
}
/**
* 調(diào)用Toast.makeText方法
* @param text 需要提示的文本
*/
fun Activity.toast(text: String) {
Toast.makeText(this, text, Toast.LENGTH_SHORT).show()
}
效果圖1
效果圖2
Github項目代碼:點我跳轉(zhuǎn)