【笔记】Android控件

前言

Android控件学习笔记

xml头

/app/src/main/res/layout/activity_main.xml

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

</LinearLayout>

TextView文本组件

基本属性设置

/app/src/main/res/layout/activity_main.xml

android:layout_width="":设置组件宽度
android:layout_height="":设置组件高度

match_parent:根据父级容器决定尺寸
wrap_content:自动决定尺寸
数字dp:手动决定尺寸,dp:屏幕密度

android:id="@+id/编号":编号
android:text="":设置文本内容
android:textColor="#FF000000":设置文字颜色,通过argb设置
android:textStyle="":设置文字风格

bold:加粗
italic:斜体
normal:缺省值,无效果

android:textSize="数字sp":设置文字大小
android:background="#FF000000":设置背景颜色,通过argb设置
android:gravity="":设置内容对齐方向

left:居左
center:居中
right:居右
top:居顶
bottom:居底

1
2
3
<TextView
android:layout_width=""
android:layout_height="" />

阴影设置

/app/src/main/res/layout/activity_main.xml

android:shadowColor="":设置阴影颜色,需要与shadowRadius一起使用
android:shadowRadius="":设置模糊。建议使用3.0
android:shadowDx="":设置阴影水平偏移量
android:shadowDy="":设置阴影垂直偏移量

1
2
3
4
5
<TextView
android:shadowColor=""
android:shadowRadius=""
android:shadowDx=""
android:shadowDy="" />

跑马灯效果

/app/src/main/res/layout/activity_main.xml

android:singleLine="true":内容单行显示,防止换行
android:ellipsize="":省略文本的位置

marquee:跑马灯效果
start:在开始省略
end:在末尾省略
middle:在中间省略
none:缺省值,超出部分不省略

android:marqueeRepeatLimit="":重复次数

marquee_forever:一直重复

android:focusable="true":允许获取焦点
android:focusableInTouchMode="true":触摸模式下允许获取焦点

1
2
3
4
5
6
7
<TextView
android:singleLine="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"

android:focusable="true"
android:focusableInTouchMode="true" />

通过Java设置控件属性

/app/src/main/java/…/MainActivity.java

通过id获取控件对象

1
TextView textView = findViewById(R.id.编号);

通过Java对象设置属性

  • Java设置的属性会覆盖标签的属性
1
textView.setText("");

使用常量池中字符串的常量

添加字符串常量

/app/src/main/res/values/strings.xml

1
<string name="键"></string>

使用字符串常量

/app/src/main/res/layout/activity_main.xml

1
2
<TextView
android:text="@string/键" />

使用常量池中颜色的常量

添加颜色常量

/app/src/main/res/values/colors.xml

1
<color name="pink">#FFFC94AF</color>

使用颜色常量

/app/src/main/res/layout/activity_main.xml

1
2
<TextView
android:textColor="@color/pink" />

Button按钮组件

  • Button继承自TextView,所以TextView拥有的属性Button也同样拥有

/app/src/main/res/layout/activity_main.xml

1
2
3
<Button
android:layout_width=""
android:layout_height="" />

踩坑

  • 旧版本gradle会出现修改按钮颜色失效的问题

解决问题

  • /app/src/main/res/values/themes.xml文件中的
    Theme.MaterialComponents.DayNight.DarkActionBar
    改为
    Theme.MaterialComponents.DayNight.DarkActionBar.Bridge

按下Button实现不同的背景色

创建一个图片选择器

  • /app/src/main/res/drawable目录下创建一个Drawable Resource File文件
  • /app/src/main/res/drawable目录下添加xml格式的图片

右键res目录->New->Vector Assset

  • android:state_pressed="true"标记的标签是点击后的图片
1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

<item android:drawable="@drawable/ic_like" android:state_pressed="true" />
<item android:drawable="@drawable/ic_sugar" />

</selector>
踩坑
  • /app/src/main/res/drawable/btn_selector.xml文件中,应该先写变化后的item,后写还原后的item,不可以改变顺序

使用图片选择器

/app/src/main/res/layout/activity_main.xml

1
2
<Button
android:background="@drawable/btn_selector" />

按钮事件

通过XML设置按钮事件

点击事件

click:对应java方法名

/app/src/main/res/layout/activity_main.xml

1
2
<Button
android:onClick="click" />

/app/src/main/java/…/MainActivity.java

1
2
3
public void click(View view) {
...
}

通过Java设置按钮事件

  • 通过Java获取组件对象

/app/src/main/java/…/MainActivity.java

1
Button btn = findViewById(R.id.btn);
点击事件

/app/src/main/java/…/MainActivity.java

1
2
3
4
5
6
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {

}
});
长按事件

/app/src/main/java/…/MainActivity.java

1
2
3
4
5
6
btn.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
return false;
}
});
触摸事件

/app/src/main/java/…/MainActivity.java

1
2
3
4
5
6
btn.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return false;
}
});
触摸的具体操作

motionEvent.getAction():获取触摸的具体操作

0:down按下
2:move在按下后移动
1:on松手

/app/src/main/java/…/MainActivity.java

1
2
3
4
5
6
7
btn.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
System.out.println(motionEvent.getAction());
return false;
}
});
打印日志

TAG:表示标记的常量
<str>:日志内容字符串

/app/src/main/java/…/MainActivity.java

1
Log.e(TAG, <str>);

EditText表单组件

  • EditText继承自TextView,所以TextView拥有的属性EditText也同样拥有

android:hint="":输入框提示文字
android:textColorHint="":提示文字颜色
android:inputType="":输入框类型

text:文本
number:数字,只弹出数字输入法
phone:电话,只弹出数字输入法
textPassword:文本密码
numberPassword:数字密码

android:drawableLeft="":在左侧添加图标
android:drawableRight="":在右侧添加图标
android:drawableTop="":在顶部添加图标
android:drawableBottom="":在底部添加图标
android:drawablePadding="":图片与输入框的间距

android:padding="":输入框与外框四周的内边距
android:paddingLeft="":输入框与外框左侧的内边距
android:paddingRight="":输入框与外框右侧的内边距
android:paddingTop="":输入框与外框顶部的内边距
android:paddingBottom="":输入框与外框顶部的内边距

/app/src/main/res/layout/activity_main.xml

1
2
3
<EditText
android:layout_width=""
android:layout_height="" />

获取输入框内容

/app/src/main/java/…/MainActivity.java

1
2
EditText editText = findViewById(R.id.et);
editText.getText().toString();

ImageView图片组件

  • 图片资源放在/app/src/main/res/drawable

android:src="":图片路径
android:scaleType="":图片缩放类型

fitCenter:缺省值,保持宽高比缩放图片,直到较长的边与Image的边长相等,缩放完成后将图片放在ImageView的中间
fitStart:保持宽高比缩放图片,直到较长的边与Image的边长相等,缩放完成后将图片放在ImageView的左上角
fitEnd:保持宽高比缩放图片,直到较长的边与Image的边长相等,缩放完成后将图片放在ImageView的右下角
fitXY:强制缩放到满,有可能不等比例
center:保持原图大小,显示在ImageView的中心,如果原图过大,可能会被裁剪
centerCrop:等比例缩放到满,显示在ImageView的中心,如果原图不等比例,可能会被裁减
centerInside:等比例缩放到满,显示在ImageView的中心,不会被裁剪
matrix:保持原图大小,显示在ImageView的左上角,如果原图过大,可能会被裁剪

android:maxWidth="":最大宽度
android:maxHeight="":最大高度
android:minWidth="":最小宽度
android:minHeight="":最小高度
android:adjustViewBounds="":根据最大宽高,自动调整View的界限为图片宽高

/app/src/main/res/layout/activity_main.xml

1
2
3
<ImageView
android:layout_width=""
android:layout_height="" />

ProgressBar进度条

style="?android:attr/progressBarStyleHorizontal":改为水平进度条
android:max="":进度条最大值
android:progress="":进度条已完成进度
android:indeterminate="true":进度条不显示进度

/app/src/main/res/layout/activity_main.xml

1
2
3
<ProgressBar
android:layout_width=""
android:layout_height="" />

改变进度条状态

获取进度条对象

/app/src/main/res/layout/activity_main.xml

1
2
<ProgressBar
android:id="@+id/pb" />

/app/src/main/java/…/MainActivity.java

1
ProgressBar progressBar = findViewById(R.id.pb);

查看当前进度条状态

/app/src/main/java/…/MainActivity.java

1
progressBar.getVisibility();

改为隐藏

/app/src/main/java/…/MainActivity.java

1
progressBar.setVisibility(View.GONE);

改为显示

/app/src/main/java/…/MainActivity.java

1
progressBar.setVisibility(View.VISIBLE);

Notification通知

发送通知

<id>:设置一个id,前后id需保持一致
<msg>:通知名称
<level>:通知的重要程度
.<init>:通过链式结构配置通知

<level> 是否开启通知 是否弹出 是否有提示音 是否状态栏中显示
NotificationManager.IMPORTANCE_NONE × - - -
NotificationManager.IMPORTANCE_MIN × × ×
NotificationManager.IMPORTANCE_LOW × ×
NotificationManager.IMPORTANCE_DEFAULT ×
NotificationManager.IMPORTANCE_HIGH
.<init> 是否必选 备注
.setContentTitle("") 必选 设置标题
.setContentText("") 必选 设置内容
.setSmallIcon(R.drawable.ic_图片名) 必选 设置小图标,必须为alpha图层,不可以包含RGB图层
.setColor() 可选 设置小图标的颜色
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_图片名)) 可选 设置大图标
.setContentIntent() 可选 设置点击通知的跳转意图
.setAutoCancel(true) 可选 设置点击后自动清除
.setWhen() 可选 设置通知创建时间,默认为当前时间

/app/src/main/java/…/MainActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 通知管理器
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// 判断系统版本是否大于8.0,为大于8.0版本的程序添加通知渠道
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel("<id>", "<msg>", <level>);
notificationManager.createNotificationChannel(notificationChannel);
}
// 创建通知
Notification notification = new NotificationCompat.Builder(this, "<id>")
.setContentTitle("")
.setContentText("")
.setSmallIcon(R.drawable.ic_)
.<init>
.build();
// 发送通知
notificationManager.notify(1, notification);

添加通知的意图

创建一个Activity类
  • 创建一个NotificationActivity类,继承Activity类,并实现onCreate()方法

/app/src/main/java/…/NotificationActivity.java

1
2
3
4
5
6
7
8
public class NotificationActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 添加意图
...
}
}
注册Activity

/app/src/main/AndroidManifest.xml

1
2
3
<application
<activity android:name=".NotificationActivity" />
</application>
为通知添加意图

/app/src/main/java/…/MainActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 通知管理器
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// 判断系统版本是否大于8.0,为大于8.0版本的程序添加通知渠道
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel("<id>", "<msg>", <level>);
notificationManager.createNotificationChannel(notificationChannel);
}
Intent intent = new Intent(this, NotificationActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
// 创建通知
Notification notification = new NotificationCompat.Builder(this, "<id>")
.setContentTitle("")
.setContentText("")
.setSmallIcon(R.drawable.ic_)
.setContentIntent(pendingIntent) // 添加意图
.setAutoCancel(true) // 点击后自动清除
.build();
// 发送通知
notificationManager.notify(1, notification);

取消通知

/app/src/main/java/…/MainActivity.java

1:这个id需要与上面发起通知时的id保持相同

1
notificationManager.cancel(1);

ToolBar导航栏

  • 通过替换ActionBar为ToolBar,实现自定义导航栏

清除自带的ActionBar

  • /app/src/main/res/values/themes.xml文件的Theme.MaterialComponents.DayNight.DarkActionBar改为Theme.MaterialComponents.DayNight.NoActionBar

添加ToolBar

app:navigationIcon="@drawable/ic_图片名":导航栏图标,通常设置成返回的图标
app:title="":标题
app:titleTextColor="":标题文字颜色
app:titleMarginStart="":标题左外间距
app:titleMarginEnd="":标题右外间距
app:titleMarginBottom="":标题下外间距
app:subtitle="":副标题
app:subtitleTextColor="":副标题文字颜色
app:logo="@drawable/ic_图片名":软件在导航栏的图标

/app/src/main/res/layout/activity_main.xml

1
2
3
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" />

点击效果

/app/src/main/res/layout/activity_main.xml

1
2
3
4
<androidx.appcompat.widget.Toolbar
android:id="@+id/tb"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" />

/app/src/main/java/…/MainActivity.java

1
2
3
4
5
6
7
Toolbar toolbar = findViewById(R.id.tb);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {

}
});

设置居中的标题

/app/src/main/res/layout/activity_main.xml

1
2
3
4
5
6
7
8
9
10
11
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="" />

</androidx.appcompat.widget.Toolbar>

AlertDialog对话框

.setIcon(R.drawable.ic_图片名):设置对话框图标
.setTitle(""):设置对话框标题
.setMessage(""):设置对话框内容

/app/src/main/java/…/MainActivity.java

1
2
3
4
5
6
7
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder
.setIcon(R.drawable.ic_)
.setTitle("")
.setMessage("")
.create() // 创建对话框
.show(); // 显示对话框

添加按钮

添加左下角按钮

/app/src/main/java/…/MainActivity.java

1
2
3
4
5
6
7
8
9
10
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder
.setNeutralButton("跳过", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {

}
})
.create() // 创建对话框
.show(); // 显示对话框

添加右下角左侧按钮

/app/src/main/java/…/MainActivity.java

1
2
3
4
5
6
7
8
9
10
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {

}
})
.create() // 创建对话框
.show(); // 显示对话框

添加右下角右侧按钮

/app/src/main/java/…/MainActivity.java

1
2
3
4
5
6
7
8
9
10
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {

}
})
.create() // 创建对话框
.show(); // 显示对话框

添加布局

创建一个布局

  • /app/src/main/res/layout/目录下创建一个dialog\_view.xml

/app/src/main/res/layout/activity_main.xml

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">

...

</LinearLayout>

将dialog_view.xml布局放到对话框

/app/src/main/java/…/MainActivity.java

1
2
3
4
5
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder
.setView(getLayoutInflater().inflate(R.layout.dialog_view, null))
.create() // 创建对话框
.show(); // 显示对话框

PopupWindow弹出窗口

创建一个布局用来弹出

  • /app/src/main/res/layout/目录下创建一个popup\_view.xml布局文件用来测试

/app/src/main/res/layout/popup_main.xml

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="200dp"
android:layout_height="200dp"
android:orientation="vertical"
android:background="@mipmap/ic_launcher">

</LinearLayout>

创建一个按钮用来弹出窗口

/app/src/main/res/layout/activity_main.xml

1
2
3
4
<Button
android:onClick="click"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

创建PopupWindow

窗口无偏移,显示在正下方

  • 在click方法中,创建PopupWindow,在按钮下方弹出次

既可以使用构造方法初始化窗口,也可以使用无参构造创建对象后,再使用set方法进行初始化

getLayoutInflater().inflate(R.layout.popup_view, null):设置弹出窗口的布局
ViewGroup.LayoutParams.WRAP_CONTENT:将弹出窗口的宽高都设置为自动wrap_content。如果需要手动设置,可以直接传递宽高

/app/src/main/java/…/MainActivity.java

1
2
3
4
public void click(View view) {
PopupWindow popupWindow = new PopupWindow(getLayoutInflater().inflate(R.layout.popup_view, null), ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
popupWindow.showAsDropDown(view);
}

窗口有偏移

/app/src/main/java/…/MainActivity.java

<x>:水平偏移量
<y>:垂直偏移量

1
2
3
4
public void click(View view) {
PopupWindow popupWindow = new PopupWindow(getLayoutInflater().inflate(R.layout.popup_view, null), ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
popupWindow.showAsDropDown(view, <x>, <y>);
}

点击空白处隐藏

/app/src/main/java/…/MainActivity.java

1
2
3
4
public void click(View view) {
PopupWindow popupWindow = new PopupWindow(getLayoutInflater().inflate(R.layout.popup_view, null), ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
popupWindow.showAsDropDown(view);
}

关闭PopupWindow

/app/src/main/java/…/MainActivity.java

1
popupWindow.dismiss();

点击空白处隐藏

/app/src/main/java/…/MainActivity.java

1
popupWindow.setFocusable(true);

设置背景

  • 设置背景需要在显示之前

/app/src/main/java/…/MainActivity.java

1
popupWindow.setBackgroundDrawable(getResources().getDrawable(R.drawable.ic_图片名));

完成

参考文献

哔哩哔哩——Android架构解析