安卓筆記
- 智能手機應用型別
- 按鈕
- 選單
- 右上角小選單
- 背景關系選單
- 文本框
- 撥打電話
- 顯示彈窗
- 訊息彈框
- 界面彈框
- 界面布局
- 顯示過長的文本
- 實作水平居中
- 實作水平和垂直居中
- 使用LinearLayout
- 使用ConstrainLayout
- 模塊集中方法
- 實作北南中布局
- 控制元件隱藏與顯示
- ConstraintLayout影片
- 界面的動態替換
- 使用ViewStub動態實體化控制元件
- CountDown倒計時
- 按鈕影片
- 設定按鈕集合
- XXOO游戲
- 新建另一個頁面
- Activity狀態與生命周期
- 概念
- 在切換橫屏豎屏時候
- 定義靜態變數
- 禁止橫豎屏旋轉
智能手機應用型別
- Mobile Web
本質上是一個傳統的Web應用 - Native App
使用Kotlin/Swift開發
使用系統原生的編程語言實作,呼叫手機硬體和作業系統的所有功能,開發量較大 - Hybrid App
本質上是一個內嵌了WebView的NativeApp
使用JavaScript撰寫
id 'kotlin-android-extensions'
按鈕
val Year = findViewById<TextView>(R.id.editText)
val textView2 = findViewById<TextView>(R.id.textView2)
val btnClick = findViewById<Button>(R.id.button)
//回應按鈕
btnClick.setOnClickListener {
val NowYear = Calendar.getInstance()[Calendar.YEAR]//日期
val InYear = Year.text.toString().toInt()
textView2.text = "您的年齡是:" + (NowYear - InYear)
}
btnChangeMyText.setOnClickListener {
counter++//事件回應函式中的第一個引數,參考按鈕物件自己
(it as Button).text = "我被扁了${counter}次! :-("
}
btnLongClick.setOnLongClickListener {
Toast.makeText(this, "長按了按鈕", Toast.LENGTH_SHORT).show()
true//回傳true表示應用程式己經處理了長按事件
}
//設定復選框的狀態
myCheckBox.isChecked = false
//回應復選框狀態的改變
myCheckBox.setOnCheckedChangeListener { buttonView, isChecked ->
//buttonView參考當前的復選框物件
//isChecked表示當前是選中還是取消
val info = if (isChecked) "勾選" else "取消勾選"
buttonView.text = "您${info}了復選框"
}
//針對單選鈕的編程,需要基于它的容器RadioGroup
rgGender.setOnCheckedChangeListener { group, checkedId ->
//checkedId表示當前選中的單選鈕Id
tvRadioButton.text = when (checkedId) {
R.id.rdoFemale -> "美女"
R.id.rdoMale -> "帥哥"
else -> "傻瓜"
}
}
var isFlower = false
btnChangeImage.setOnClickListener {
if (isFlower) {
image.setImageResource(R.drawable.forest)
} else {
image.setImageResource(R.drawable.flower)
}
isFlower = !isFlower
}
//使用ImageAsset
image.setImageResource(R.mipmap.ic_launcher)
rGroup.setOnCheckedChangeListener { group, checkedId ->
when (checkedId) {
R.id.center -> image.setScaleType(ImageView.ScaleType.FIT_CENTER)
R.id.fitend -> image.setScaleType(ImageView.ScaleType.FIT_END)
R.id.fitstart -> image.setScaleType(ImageView.ScaleType.FIT_START)
}
}//when就是switch
選單
右上角小選單
File name: mymenu
Recource type: Menu
Directory name: menu
ShowAsAction:ifRoom有空間則顯示,always始終顯示,withText同時顯示文本
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
super.onCreateOptionsMenu(menu)
//設定在任何情況下均顯示圖示
setIconEnable(menu!!,true);
//加載選單資源
menuInflater.inflate(R.menu.mymenu,menu)
return true
}
//Hack手段,使用反射打開“顯示選單項圖示”功能
private fun setIconEnable(menu: Menu, enable: Boolean) {
try {
val clazz =
Class.forName("androidx.appcompat.view.menu.MenuBuilder")
val m: Method = clazz.getDeclaredMethod(
"setOptionalIconsVisible",
Boolean::class.javaPrimitiveType
)
m.isAccessible = true
//下面傳入引數
m.invoke(menu, enable)
} catch (e: Exception) {
e.printStackTrace()
}
}
//相應選單點擊事件
override fun onOptionsItemSelected(item: MenuItem): Boolean {
super.onOptionsItemSelected(item)
when(item.itemId){
R.id.mnuAbout->tvInfo.text="About"
R.id.mnuEdit->tvInfo.text="Edit"
R.id.mnuExit->finish()
R.id.mnuNew->tvInfo.text="New"
R.id.mnuOpen->tvInfo.text="Open"
R.id.mnuSave->tvInfo.text="Save"
}
return true
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
super.onCreateOptionsMenu(menu)
menuInflater.inflate(R.menu.menu, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == R.id.about_item) {
showInfo()
}
return true
}
private fun showInfo() {
val dialogTitle = "關于"
val dialogMessage = "倒計時計數器 ver 1.0 \n\n開發:金旭亮"
val builder = AlertDialog.Builder(this)
builder.setTitle(dialogTitle)
builder.setMessage(dialogMessage)
builder.create().show()
}
背景關系選單
File name:mycontext_menu
Directory name: menu
Recource type: Menu
registerForContextMenu(tvInfo)// 給控制元件注冊背景關系選單
override fun onCreateContextMenu(
menu: ContextMenu?,
v: View?,
menuInfo: ContextMenu.ContextMenuInfo?
) {
super.onCreateContextMenu(menu, v, menuInfo)
menuInflater.inflate(R.menu.mycontext_menu,menu)
}
override fun onContextItemSelected(item: MenuItem): Boolean {
val info= when(item.itemId){
R.id.main_ctxmenu_deleteCommunicator->
"選中了:main_ctxmenu_deleteCommunicator"
R.id.main_ctxmenu_editCommunicator->
"選中了:main_ctxmenu_editCommunicator"
else -> "選中了:main_ctxmenu_sendMessage"
}
tvInfo.text=info
return true
}
文本框
EditText
intputType屬性:用于限制用戶只能輸?數字等特定的字符
text屬性:用于取出用戶輸?的字串
maxLength屬性:用于設定用戶能輸?的最?字符數
edtPhone.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
}
override fun beforeTextChanged(s: CharSequence?, start: Int,
count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int,
before: Int, count: Int) {
val strLength = s.toString()?.length
if (strLength == 11) {
tvInfo.text = "您輸入的手機號碼是:${s}"
} else {
tvInfo.text = "還剩余${11 - strLength}個數字"
}
}
})
btnCall.setOnClickListener {
callPhone(edtPhone.text.toString())
}
撥打電話
在AndroidManifest.xml中宣告權限:
<uses-permission android:name="android.permission.CALL_PHONE"/>
顯示彈窗
訊息彈框
Toast.makeText(this, "長按了按鈕", Toast.LENGTH_SHORT).show()
界面彈框
private fun showInfo() {
val dialogTitle = "關于"
val dialogMessage = "倒計時計數器 ver 1.0 \n\n開發:金旭亮"
val builder = AlertDialog.Builder(this)
builder.setTitle(dialogTitle)
builder.setMessage(dialogMessage)
builder.create().show()
}
界面布局
Margin:元素之間的間距
Padding:元素內部具體內容與元素外邊界之間的區域
固定值:100sp
warp_content:數值依控制元件所顯示的內容而定
match_parent:與其父空間的數值相匹配(一致)
fill_parent:
dp:
160dpi螢屏上 1dp1像素
480dpi螢屏上 1dp3像素
使用ConstraintLayout
在build.gradle 中添加以下依賴:
implementation 'androidx.constraintlayout:constraintlayout:1.1.3 '
顯示過長的文本
將有可能超出螢屏的布局放到scrollView控制元件中,即可自動給其添加滾動查看功能,
實作水平居中
使用LinearLayout
?控制元件寬度設定為match_parent,然后讓其內容居中,以TextView為例,這是通過設定它的textAligment(?本對齊?式)實作center
?控制元件寬?度均設定為wrap_content,可以使用layout_gravity讓其“顯示位置居中center_horizontal
實作水平和垂直居中
使用LinearLayout
讓?控制元件的寬度?度占滿?控制元件,然后設定gravity和textAlignment讓其“內容居中”,center
使用ConstrainLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintVertical_bias="0.5"
模塊集中方法

實作北南中布局
使用LinearLayout
頂部和底部都有控制元件,中部依據螢屏?小自動切換,
中間可用RecyclerView作為示例控制元件,設定layout_weight實作自動鋪滿可用空間,
layout_height = “0dp”
layout_weight = “1”
控制元件隱藏與顯示
android:visibility=“gone”:不顯示此按件,它不參與布局
android:visibility=“invisible”:不顯示此按件,但它參與布局,在界面上會留有位置
android:visibility=“visible”:此控制元件正常顯示
ConstraintLayout影片
//定義兩個約束集,分別對應兩個影片狀態(即關鍵幀)
val constraintSet = ConstraintSet()
val constraintSet2 = ConstraintSet()
//定義影片物件
val transition = ChangeBounds()
//這個標記用于在兩個影片狀態之間反復切換
var flag = true
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//分別裝載兩個布局檔案的約束集
constraintSet.load(this, R.layout.activity_main)
constraintSet2.load(this, R.layout.activity_main2)
//設定影片屬性
transition.interpolator = AnticipateOvershootInterpolator(1.0f)
transition.duration = 1000
//點擊Activity時,啟動影片
rootContainer.setOnClickListener {
animateToKeyframe()
}
}
fun animateToKeyframe() {
//開始影片
TransitionManager.beginDelayedTransition(rootContainer, transition)
if (flag) {
constraintSet2.applyTo(rootContainer)
} else {
constraintSet.applyTo(rootContainer)
}
flag = !flag
}
界面的動態替換
在Activity中需要時隨時呼叫setContentView(R.layout.布局?件ID);即可,動態切換的布局可共享Activity中的成員變數,
使用代碼創建控制元件實體,然后呼叫ViewGroup的addView?法加?到控制元件樹中
(1)直接用new關鍵字實體化
(2)使用LayoutInflator基于XML布局進?實體化
在不需要時,可以隨時呼叫ViewGroup.removeView()?法從控制元件樹中移除特定的控制元件,
var counter = 0
btnAdd.setOnClickListener {
counter++
//從XML布局檔案中加載并實體化一個TextView控制元件物件
val textView = layoutInflater.inflate(R.layout.my_textview, null) as TextView
//設定TextView控制元件顯示的文本
textView.text = "新控制元件${counter}"
//給其掛接事件回應
textView.setOnClickListener {
Toast.makeText(this, "${(it as TextView).text}", Toast.LENGTH_SHORT)
.show()
}
//追加到控制元件容器中
viewContainer.addView(textView)
}
btnRemoveAllView.setOnClickListener {
viewContainer.removeAllViews()
}
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:text="新控制元件"
android:textAlignment="center"
android:textColor="#ff0000"
android:textSize="20sp">
</TextView>
使用ViewStub動態實體化控制元件
示例每次運?時,都隨機地確定到底使用哪個布局,
可以為ViewStub指定?個布局,在inflate布局的時候,只有ViewStub會被初始化,然后當viewstub被設定為可見的時候,或者呼叫了inflate?法的時候, ViewStub所指向的布局就會被inflate和實體化,然后ViewStub的布局屬性都會傳給所指向的布局,這樣就可以使用ViewStub來?便在運?時有選擇的顯示某?個布局,
fun randomChangeView() {
val ranValue = Random().nextInt(100)
if (ranValue > 49) {
viewstub_textview.inflate()
val textView = findViewById<TextView>(R.id.viewstub_demo_textview)
textView.text = "viewstub是一個輕量級的 view," +
"可以為viewstub指定一個布局," +
"在inflate布局的時候,只有viewstub會被初始化."
} else {
viewstub_iamgeview.inflate()
val imageView = findViewById<ImageView>(R.id.viewstub_demo_imageview)
imageView.setImageResource(R.drawable.test)
}
}
//activity_main.xml中
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal">
<ViewStub
android:id="@+id/viewstub_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="10dp"
android:layout="@layout/viewstub_textview_layout"/>
<ViewStub
android:id="@+id/viewstub_iamgeview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout="@layout/viewstub_imageview_layout"/>
</LinearLayout>
//viewstub_imageview_layout.xml中
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/viewstub_demo_imageview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
//viewstub_textview_layout.xml中
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/viewstub_demo_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#aa664411"
android:textSize="16sp"/>
</LinearLayout>
CountDown倒計時
//CountDownTimer是一個抽象基類
private lateinit var countDownTimer: CountDownTimer
private var timeLeft = 60
private var isStart = false
private fun startCountDown() {
timeLeft = 30
isStart = true
countDownTimer = object : CountDownTimer(30000, 1000) {
override fun onFinish() {
Toast.makeText(this@MainActivity, "時間到!", Toast.LENGTH_LONG).show()
btnCountDown.isEnabled = true、、//倒計時結束后才能開始點擊
}
override fun onTick(millisUntilFinished: Long) {
timeLeft = millisUntilFinished.toInt() / 1000
tvInfo.text = "${timeLeft}"
}
}
countDownTimer.start()
}
private fun cancelCountDown() {
if (!isStart)
return
countDownTimer.cancel()
btnCountDown.isEnabled = true//點擊完取消后就可以點擊開始了
}
按鈕影片
btnCountDown.setOnClickListener {
//裝載影片
val bounceAnimation = AnimationUtils.loadAnimation(
this,
R.anim.bounce
)
it.startAnimation(bounceAnimation)
}
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
android:interpolator="@android:anim/bounce_interpolator"
>
<scale
android:duration="2000"
android:fromXScale="2.0"
android:fromYScale="2.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.0"
android:toYScale="1.0" />
</set>
設定按鈕集合
為每一個按鈕都設定上onclick為btnClick這樣在按下九宮格的時候就都會有反應
fun btnClick(view: View) {
val btnSelected = view as Button
var cellId = 0
when (btnSelected.id) {
R.id.btn1 -> cellId = 1
R.id.btn2 -> cellId = 2
R.id.btn3 -> cellId = 3
R.id.btn4 -> cellId = 4
R.id.btn5 -> cellId = 5
R.id.btn6 -> cellId = 6
R.id.btn7 -> cellId = 7
R.id.btn8 -> cellId = 8
R.id.btn9 -> cellId = 9
}
playGame(cellId, btnSelected)
}
XXOO游戲
package com.example.tictactoy
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_main.*
import java.util.*
import kotlin.collections.ArrayList
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
fun btnClick(view: View) {
val btnSelected = view as Button
var cellId = 0
when (btnSelected.id) {
R.id.btn1 -> cellId = 1
R.id.btn2 -> cellId = 2
R.id.btn3 -> cellId = 3
R.id.btn4 -> cellId = 4
R.id.btn5 -> cellId = 5
R.id.btn6 -> cellId = 6
R.id.btn7 -> cellId = 7
R.id.btn8 -> cellId = 8
R.id.btn9 -> cellId = 9
}
playGame(cellId,btnSelected)
}
var player1=ArrayList<Int>()
var player2=ArrayList<Int>()
var activePlayer=1
fun playGame(cellId:Int,btnSelected:Button){
if(activePlayer==1){
btnSelected.text="X"
btnSelected.setBackgroundColor(Color.GREEN)
player1.add(cellId)
activePlayer=2
autoPaly()
}else{
btnSelected.text="O"
btnSelected.setBackgroundColor(Color.YELLOW)
player2.add(cellId)
activePlayer=1
}
btnSelected.isEnabled=false
checkWinner()
}
fun checkWinner(){
var winner=-1
//第一行
if(player1.contains(1) && player1.contains(2) && player1.contains(3)){
winner=1
}
if(player2.contains(1) && player2.contains(2) && player2.contains(3)){
winner=2
}
//第二行
if(player1.contains(4) && player1.contains(5) && player1.contains(6)){
winner=1
}
if(player2.contains(4) && player2.contains(5) && player2.contains(6)){
winner=2
}
//第三行
if(player1.contains(7) && player1.contains(8) && player1.contains(9)){
winner=1
}
if(player2.contains(7) && player2.contains(8) && player2.contains(9)){
winner=2
}
//------------------
//第一列
if(player1.contains(1) && player1.contains(4) && player1.contains(7)){
winner=1
}
if(player2.contains(1) && player2.contains(4) && player2.contains(7)){
winner=2
}
//第二列
if(player1.contains(2) && player1.contains(5) && player1.contains(8)){
winner=1
}
if(player2.contains(2) && player2.contains(5) && player2.contains(8)){
winner=2
}
//第三列
if(player1.contains(3) && player1.contains(6) && player1.contains(9)){
winner=1
}
if(player2.contains(3) && player2.contains(6) && player2.contains(9)){
winner=2
}
//-----------------------------
//TODO:添加對于對角線的檢查
//-------------------
if(winner!= -1){
Toast.makeText(this,"Player${winner} win",Toast.LENGTH_SHORT).show()
}
}
fun autoPaly(){
val emptyCells=ArrayList<Int>()
for(cellId in 1..9){
if(!(player1.contains(cellId) || player2.contains(cellId))){
emptyCells.add(cellId)
}
}
val ranIndex= Random().nextInt(emptyCells.size)
val cellId=emptyCells[ranIndex]
var btnSelected:Button?
when(cellId){
1->btnSelected=btn1
2->btnSelected=btn2
3->btnSelected=btn3
4->btnSelected=btn4
5->btnSelected=btn5
6->btnSelected=btn6
7->btnSelected=btn7
8->btnSelected=btn8
else->btnSelected=btn9
}
playGame(cellId,btnSelected)
}
}
<?xml version="1.0" encoding="utf-8"?>
<TableLayout 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:gravity="center"
tools:context=".MainActivity">
<TableRow
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:onClick="btnClick"
android:id="@+id/btn1"
android:layout_width="40pt"
android:layout_height="40pt" />
<Button
android:onClick="btnClick"
android:id="@+id/btn2"
android:layout_width="40pt"
android:layout_height="40pt" />
<Button
android:onClick="btnClick"
android:id="@+id/btn3"
android:layout_width="40pt"
android:layout_height="40pt" />
</TableRow>
<TableRow
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:onClick="btnClick"
android:id="@+id/btn4"
android:layout_width="40pt"
android:layout_height="40pt" />
<Button
android:onClick="btnClick"
android:id="@+id/btn5"
android:layout_width="40pt"
android:layout_height="40pt" />
<Button
android:onClick="btnClick"
android:id="@+id/btn6"
android:layout_width="40pt"
android:layout_height="40pt" />
</TableRow>
<TableRow
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:onClick="btnClick"
android:id="@+id/btn7"
android:layout_width="40pt"
android:layout_height="40pt" />
<Button
android:onClick="btnClick"
android:id="@+id/btn8"
android:layout_width="40pt"
android:layout_height="40pt" />
<Button
android:onClick="btnClick"
android:id="@+id/btn9"
android:layout_width="40pt"
android:layout_height="40pt" />
</TableRow>
</TableLayout>
新建另一個頁面
setContentView(R.layout.activity_other)
Activity狀態與生命周期
概念
五個狀態:Initialized Created Started Resumed Destroyed
生命周期:
- onCreate 初始化Activity內部欄位,設定Activity布局
- onRestart Activity進入已啟動狀態,對用戶可見
- onResume Activity已經準備好,可以相應用戶輸入
- onPause Activity失去焦點并進入“已暫停狀態”
- onStop Activity不可見,再次釋放用不著的資源
- onDestrory Activity將被作業系統銷毀,在此釋放所有資源


在切換橫屏豎屏時候
之所以用戶旋轉螢屏時狀態會丟失,是因為Android把原先的Activity銷毀了
這樣做可以使界面布局改變時保存所需要的值
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btnClickMe.setOnClickListener {
counter++
tvCount.text = "計數值:${counter}"
}
//恢復實體資料
if (savedInstanceState != null) {
counter = savedInstanceState.getInt("counter")
tvCount.text = "計數值:${counter}"
}
}
var counter = 0
override fun onSaveInstanceState(outState: Bundle) {
//保存實體資料
outState.putInt("counter", counter)
Log.d("MainActivity", "計數值己保存:$counter")
Toast.makeText(this, "保存", Toast.LENGTH_SHORT).show()
super.onSaveInstanceState(outState)
}
定義靜態變數
companion object {
var globalCount: Int = 0
}
禁止橫豎屏旋轉
# 增添上
<activity android:name=".MainActivity" android:screenOrientation="portrait">
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/255247.html
標籤:其他
上一篇:Android Studio4.1.2升級之后代碼不高亮了,代碼自動提示功能沒有
下一篇:Android學習記錄(二十一)
