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中声明权限:
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
让⼦控件的宽度⾼度占满⽗控件,然后设置gravity和textAlignment让其“内容居中”,center
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”:此控件正常显示
//定义两个约束集,分别对应两个动画状态(即关键帧)
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指定⼀个布局,在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>
//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)
}
<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)
}
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)
}
}
<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)
五个状态:Initialized Created Started Resumed Destroyed
生命周期:
之所以用户旋转屏幕时状态会丢失,是因为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">