Android 开发入门(4)
0x06 中级控件
(1)图形绘制
a. 图形 Drawable
-
Drawable 类型包括图片、色块、画板、背景
-
drawable 目录一般保存描述性 XML 文件,具有具体分辨率的 drawable 目录下保存图片文件
目录后缀 分辨率等级 举例 应用场景 ldpi 低分辨率 240×320 - mdpi 中分辨率 320×480 - hdpi 高分辨率 480×800 4~4.5英寸手机 xhdpi 加高分辨率 720×1280 5~5.5英寸手机 xxhdpi 超高分辨率 1080×1920 6~6.5英寸手机 xxxhdpi 超超高分辨率 1440×2560 7英寸以上平板电脑
b. 形状图形
- Shape 图形又称形状图形,用来描述常见几何图形,如矩形、圆角矩形、圆形、椭圆形等。形状图形的定义文件是以
<shape></spape>
为根节点的 XML 描述文件
-
形状 shape
- rectangle:矩形
- oval:椭圆形,此时
<corners>
节点会失效 - line:直线,此时必须设置
<stroke>
节点 - ring:圆环
-
尺寸 size
- height:像素类型,图形高度
- width:像素类型,图形宽度
-
描边 stroke
- color:颜色类型,描边的颜色
- dashGap:像素类型,每段虚线间的间隔
- dashWidth:像素类型,每段虚线的宽度
- width:像素类型,描边的厚度
-
圆角 corners
- bottomLeftRadius:像素类型,左下圆角半径
- bottomRightRadius:像素类型,右下圆角半径
- topLeftRadius:像素类型,左上圆角半径
- topRightRadius:像素类型,右上圆角半径
- radius:像素类型,统一设置四个圆角半径
-
填充 solid
- color:颜色类型,内部填充的颜色
-
间隔 padding
- top:像素类型,与上方间隔
- left:像素类型,与左侧间隔
- right:像素类型,与右侧间隔
- bottom:像素类型,与下方间隔
-
渐变 gradient
-
angle:整形,渐变的起始角度
取值方法,以表盘为例:0: 9点钟、90: 6点钟、180: 3点钟、270: 12点钟
-
type:字符串类型,设置渐变类型
- linear:线性渐变
- radial:放射渐变
- sweep:滚动渐变
-
centerX:浮点型,圆心 X 坐标
-
centerY:浮点型,圆心 Y 坐标
-
gradientRadius:整形,渐变的半径
-
centerColor:颜色类型,渐变的中间颜色
-
startColor:颜色类型,渐变的起始颜色
-
endColor:颜色类型,渐变的终止颜色
-
useLevel:布尔类型,设置为 true 时无渐变色
-
举例:
-
绘图
<!-- 金色灰边圆角矩形 --> <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#ffdd66" /> <stroke android:width="10dp" android:color="#aaaaaa" /> <corners android:radius="10dp" /> </shape> 其中,一个文件对应一个图形
-
调用
<Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="金色传说" /> View vc = findViewById(R.id.btn); vc.setBackgroundResource(R.drawable.rect); 对于按钮默认背景颜色固定为蓝紫色的情况时,可修改 /values/theme/theme.xml 文件,修改
<style>
标签 parent 属性为:parent="Theme.MaterialComponents.DayNight.DarkActionBar.Bridge"
c. 九宫格图片
将某张图片设置为背景时,如果图片尺寸太小,则系统会自动拉伸图片使之填满背景
为了解决上述问题,可以将图片转换为 9-Patch 文件,通过调整图片的边缘线来控制图片放大后的效果
- 上边缘线:控制水平方向的拉伸区域,保证左右两边边框厚度不变
- 左边缘线:控制垂直方向的拉伸区域,保证上下两边边框厚度不变
- 下边缘线:控制控件内部的文字左右边界
- 右边缘线:控制控件内部的文字上下边界
d. 状态列表图形
Button 控件在被按下的前后不同状态下的背景,由状态列表图形控制
-
/res/drawable/btn_selector.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:drawable="@drawable/btn_pressed" /> <item android:drawable="@drawable/btn_normal" /> </selector> -
btn_pressed.xml:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#aaaaaa" /> <stroke android:width="10dp" android:color="#ffff88" /> <corners android:radius="10dp" /> </shape> -
btn_normal.xml:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#ffdd66" /> <stroke android:width="10dp" android:color="#ffff00" /> <corners android:radius="10dp" /> </shape>
-
-
activity_main.xml:
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="默认按钮" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/btn_selector" android:text="自定义按钮" />
状态类型取值:
状态类型的属性名称 | 说明 | 适用的控件 |
---|---|---|
state_pressed | 是否按下 | 按钮 |
state_checked | 是否勾选 | 单选按钮、复选框 |
state_focused | 是否获取焦点 | 文本编辑框 |
state_selected | 是否选中 | 各控件通用 |
(2)选择按钮
CompoundButton 类是抽象的复合按钮,以下按钮由该类派生而来
该类在 XML 文件中主要使用以下两个属性
- checked:布尔值,指定按钮的勾选状态
- button:指定勾选图标的图形资源
该类在 Java 文件中主要使用以下四个方法
- setChecked:设置按钮的勾选状态
- setButtonDrawable:设置勾选图标的图形资源
- setOnCheckedChangeListener:设置勾选状态变化的监听器
- isChecked:判断按钮是否勾选
a. 复选框
<CheckBox android:id="@+id/cb" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:text="初始状态" />
b. 开关
<Switch android:id="@+id/sw" android:layout_width="wrap_content" android:layout_height="wrap_content" />
- textOn:设置右侧开启时的文本
- textOff:设置左侧关闭时的文本
- track:设置开关轨道的背景
- thumb:设置开关标识的图标
// import ... import android.widget.CompoundButton; import android.widget.Switch; import android.widget.TextView; public class Activity1 extends AppCompatActivity implements CompoundButton.OnCheckedChangeListener { private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_1); tv = findViewById(R.id.tv); ((Switch)findViewById(R.id.sw)).setOnCheckedChangeListener(this); } @Override public void onCheckedChanged(CompoundButton compoundButton, boolean b) { String res = String.format("当前状态:%s", (b ? "on" : "off")); tv.setText(res); } }
c. 单选按钮
单选按钮要在一组按钮中选中其中一项,用于确定按钮组范围的容器为 RadioGroup,其本质上是一种布局,同一组 RadioButton 和其他控件共同放在 RadioGroup 节点下
<RadioGroup android:id="@+id/rg" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <RadioButton android:id="@+id/y" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="同意" /> <RadioButton android:id="@+id/n" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="不同意" /> </RadioGroup>
// import ... import android.widget.RadioGroup; import android.widget.TextView; public class Activity1 extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener { private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_1); tv = findViewById(R.id.tv); RadioGroup rg = findViewById(R.id.rg); rg.setOnCheckedChangeListener((RadioGroup.OnCheckedChangeListener) this); } @Override public void onCheckedChanged(RadioGroup radioGroup, int i) { tv.setText("选择了 " + ((TextView)findViewById(i)).getText()); } }
check()
:选中指定资源编号的单选按钮getCheckedRadioButtonId()
:获取已选中的单选按钮的资源编号setOnCheckedChangeListener()
:设置单选按钮勾选变化的监听器
(3)文本输入
a. 编辑框 EditText
-
EditText 用于接收软键盘输入的文字,由 TextView 派生而来
-
EditText 具有除 TextView 全部属性外,以下特殊的 XML 属性:
-
inputType:指定输入的文本类型
输入类型 说明 text 一般文本 textPassword 文本密码,由 ·
代替输入内容number 整数 numberSigned 带符号整数 numberDecimal 浮点数 numberPassw 数字密码,由 ·
代替输入内容datetime 时间日期格式,包括数字、横线、斜线、空格、冒号 date 日期格式,包括数字、横线、斜线 time 时间格式,包括数字、冒号 -
maxLength:指定输入的最大长度
-
hint:指定提示文本内容
-
textColorHint:指定提示文本颜色
-
-
通过
android:background
属性修改编辑框背景-
背景形状 /drawable/bg.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="@color/white" /> <stroke android:width="1dp" android:color="#0000ff" /> <corners android:radius="5dp" /> <padding android:bottom="5dp" android:left="5dp" /> </shape> -
设置编辑框
<EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="text" android:background="@drawable/bg" />
-
b. 焦点变更监听器
- 编辑框点击两次后才会触发点击事件,第一次点击只触发焦点变更事件,第二次点击触发点击事件
- 若判断是否切换编辑框输入,应当监听焦点变更事件,而非监听点击事件
- 调用编辑框对象的
setOnFocusChangeListener()
方法即可在光标切换时触发焦点变更事件
举例:输入并验证 11 位手机号
-
XML
<EditText android:id="@+id/et_ph" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="number" android:hint="输入 11 位有效手机号" android:background="@drawable/bg" android:maxLength="11" /> <EditText android:id="@+id/et_pw" android:layout_width="match_parent" android:layout_height="wrap_content" /> -
Java
// import ... import android.text.TextUtils; import android.view.View; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; public class Activity1 extends AppCompatActivity implements View.OnFocusChangeListener { private TextView tv; private EditText et_1; private EditText et_2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_1); tv = findViewById(R.id.tv); et_1 = findViewById(R.id.et_ph); et_2 = findViewById(R.id.et_pw); et_2.setOnFocusChangeListener(this); } @Override public void onFocusChange(View view, boolean b) { if (b) { String phone = et_1.getText().toString(); if (TextUtils.isEmpty(phone) || phone.length() < 11) {// 判空或位数不足 // 设置焦点 et_1.requestFocus(); // 设置提示 Toast.makeText(this, "请正确输入 11 位手机号码", Toast.LENGTH_SHORT).show(); } } } }
c. 文本变化监听器
- 调用编辑框对象的
addTextChangedListener()
方法即可注册文本监听器 - 文本监听器的接口名称为 TextWatch,有以下三个监控方法
- beforeTextChanged:在文本改变前触发
- onTextChanged:在文本改变过程中触发
- afterTextChanged:在文本改变后触发
举例:完成输入指定长度的文本后自动关闭软键盘
-
HideInputMethod.java
package com.example.test.util; import android.app.Activity; import android.content.Context; import android.view.View; import android.view.inputmethod.InputMethodManager; public class HideInputMethod { public static void hideInputMethod(Activity act, View v) { InputMethodManager imm = (InputMethodManager) act.getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(v.getWindowToken(), 0); } } -
Activity1.java
// import ... import android.text.Editable; import android.text.TextWatcher; import android.widget.EditText; import com.example.test.util.HideInputMethod; public class Activity1 extends AppCompatActivity { private EditText et_ph; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_1); et_ph = findViewById(R.id.et_ph); et_ph.addTextChangedListener(new HideTextWatcher(et_ph, 11)); } private class HideTextWatcher implements TextWatcher { private EditText et; private int ml; public HideTextWatcher(EditText et, int maxLength) { // 构造函数 this.et = et; this.ml = maxLength; } @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {} @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {} @Override public void afterTextChanged(Editable editable) { String s = editable.toString(); if (s.length() == ml) { HideInputMethod.hideInputMethod(Activity1.this, et); } } } }
(4)对话框
a. 提醒 AlertDialog
- AlertDialog 可以完成常见的交互操作,其借助建造器 AlertDialog.Builder 才能完成参数设置
- 调用建造器的 create 方法生成对话框实例,在调用对话框实例的 show 方法,在页面上弹出
@Override public void onClick(View view) { // 建造器 AlertDialog.Builder builder = new AlertDialog.Builder(this); // 设置标题 builder.setTitle("致用户"); // 设置内容 builder.setMessage("是否确认"); // 设置确认事件 builder.setPositiveButton("确认", (dialogInterface, i) -> { tv.setText("确认了"); }); // 设置否定事件 builder.setNegativeButton("取消", (dialogInterface, i) -> { tv.setText("取消了"); }); // 创建对话框 AlertDialog dialog = builder.create(); // 展示对话框 dialog.show(); }
b. 日期 DatePickerDialog
-
日期选择器 DatePicker 可以让用户选择年月日信息,其并非弹窗模式,不会自动关闭
<DatePicker android:layout_width="match_parent" android:layout_height="wrap_content" android:datePickerMode="spinner" android:calendarViewShown="false" /> // import ... import android.view.View; import android.widget.DatePicker; import android.widget.TextView; public class Activity1 extends AppCompatActivity implements View.OnClickListener { private TextView tv; private DatePicker dp; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_1); tv = findViewById(R.id.tv); dp = findViewById(R.id.dp); findViewById(R.id.btn).setOnClickListener(this); } @Override public void onClick(View view) { String str = String.format("选择了:%s年%s月%s日", dp.getYear(), dp.getMonth() + 1, dp.getDayOfMonth()); tv.setText(str); } } -
DatePickerDialog 相当于在 AlertDialog 中装载了 DatePicker
- 监听器
OnDateSetLinener
负责响应日期选择事件 - 监听器中方法
onDateSet()
用于获取用户选择的日期
// import ... import android.app.DatePickerDialog; import android.view.View; import android.widget.DatePicker; import android.widget.TextView; import java.util.Calendar; public class Activity1 extends AppCompatActivity implements View.OnClickListener, DatePickerDialog.OnDateSetListener { private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_1); tv = findViewById(R.id.tv); findViewById(R.id.btn).setOnClickListener(this); } @Override public void onClick(View view) { Calendar calendar = Calendar.getInstance(); DatePickerDialog datePickerDialog = new DatePickerDialog(this, this, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH)); datePickerDialog.show(); } @Override public void onDateSet(DatePicker datePicker, int i, int i1, int i2) { String str = String.format("选择了:%s年%s月%s日", i, i1 + 1, i2); tv.setText(str); } } - 监听器
c. 时间 TimePickerDialog
- 日期选择器 DatePicker 可以让用户选择时、分信息
- TimePickerDialog 用法与 DatePickerDialog 类似
本文作者:SRIGT
本文链接:https://www.cnblogs.com/SRIGT/p/17266592.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步