主頁 > 移動端開發 > 安卓筆記

安卓筆記

2021-02-01 12:55:14 移動端開發

安卓筆記

  • 智能手機應用型別
  • 按鈕
  • 選單
    • 右上角小選單
    • 背景關系選單
  • 文本框
  • 撥打電話
  • 顯示彈窗
    • 訊息彈框
    • 界面彈框
  • 界面布局
    • 顯示過長的文本
    • 實作水平居中
    • 實作水平和垂直居中
      • 使用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螢屏上 1dp
3像素

使用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學習記錄(二十一)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more