Android 开发 - 控件(ConstraintLayout、Guideline、SeekBar、Chronometer、RecyclerView、Toolbar) - 实践

一、ConstraintLayout

1、基本介绍
  • ConstraintLayout 是 Android 开发中一种非常强大且灵活的布局管理器,它允许通过约束(Constraints)来定义视图(View)之间的相对位置和尺寸关系,与传统的布局方式(例如,LinearLayout、RelativeLayout)相比,ConstraintLayout 提供了更高的性能和更精细的布局控制,ConstraintLayout 有如下特点
  1. 性能优化:由于减少了嵌套布局的数量,ConstraintLayout 通常比传统的布局方式具有更好的性能

  2. 直观且灵活的布局定义:可以使用视觉编辑器或代码来定义视图的约束,从而轻松创建复杂的布局结构

  3. 支持扁平化布局:通过减少布局嵌套层级,有助于减少视图层次结构,提高渲染性能

  • 在 ConstraintLayout 中,可以使用一系列类似的属性来定义视图之间的水平和垂直对齐关系,这些属性以 layout_constraint 开头,后面跟着一个表示边缘(例如,left、right、top、bottom、start、end)的字符串,然后是另一个表示对齐关系的字符串(例如,leftOf、rightOf、topOf、bottomOf、startOf、endOf),最后是 parent 或者另一个视图的 ID
属性说明
layout_constraintLeft_toLeftOf将当前视图的左侧边缘与另一个视图的左侧边缘对齐
layout_constraintLeft_toRightOf将当前视图的左侧边缘与另一个视图的右侧边缘对齐
layout_constraintRight_toLeftOf将当前视图的右侧边缘与另一个视图的左侧边缘对齐
layout_constraintRight_toRightOf将当前视图的右侧边缘与另一个视图的右侧边缘对齐
layout_constraintTop_toTopOf将当前视图的顶部边缘与另一个视图的顶部边缘对齐
layout_constraintTop_toBottomOf将当前视图的顶部边缘与另一个视图的底部边缘对齐
layout_constraintBottom_toTopOf将当前视图的底部边缘与另一个视图的顶部边缘对齐
layout_constraintBottom_toBottomOf将当前视图的底部边缘与另一个视图的底部边缘对齐
layout_constraintHorizontal_bias用于调整视图在其水平约束范围内的偏移量
它接收一个 0.0 ~ 1.0 的浮点数值,表示视图应该偏向其水平约束边界的百分比
layout_constraintVertical_bias用于调整视图在其垂直约束范围内的偏移量
它接收一个 0.0 ~ 1.0 的浮点数值,表示视图应该偏向其垂直约束边界的百分比
  • 除此以外还有一些属性,它们考虑到了从右到左的语言环境(例如,阿拉伯语),在这些环境中,视图的开始(Start)和结束(End)方向可能与常规从左到右的语言环境(例如,英语)相反
属性说明
layout_constraintStart_toStartOf将当前视图的开始边缘与另一个视图的开始边缘对齐
layout_constraintStart_toEndOf将当前视图的开始边缘与另一个视图的结束边缘对齐
layout_constraintEnd_toStartOf将当前视图的结束边缘与另一个视图的开始边缘对齐
layout_constraintEnd_toEndOf将当前视图的结束边缘与另一个视图的结束边缘对齐
2、演示
  • activity_constraint_layout.xml
<?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".ConstraintLayoutActivity">
  <Button
    android:id="@+id/button_confirm"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="确定"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toLeftOf="@id/button_cancel"
    app:layout_constraintHorizontal_bias="0.5"/>
  <Button
    android:id="@+id/button_cancel"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="取消"
    app:layout_constraintTop_toTopOf="@id/button_confirm"
    app:layout_constraintBottom_toBottomOf="@id/button_confirm"
    app:layout_constraintLeft_toRightOf="@id/button_confirm"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintHorizontal_bias="0.5"/>
</androidx.constraintlayout.widget.ConstraintLayout>

二、Guideline

1、基本介绍
  • Guideline 是 ConstraintLayout 中的一个组件,它用于在布局中创建一条不可见的线,用于辅助其他视图组件的对齐和定位,Guideline 本身并不显示任何内容,它可以作为其他视图的参考点,Guideline 有三个重要的属性,但每个 Guideline 只能指定其中一个
属性说明
layout_constraintGuide_begin用于指定 Guideline 左侧或顶部的固定距离
layout_constraintGuide_end用于指定 Guideline 右侧或底部的固定距离
layout_constraintGuide_percent用于指定 Guideline 在父控件中的宽度或高度的百分比位置
例如设置为 0.8,则 Guideline 会出现在距离顶部或左侧 80% 的位置
2、演示
  1. activity_guideline_1.xml
<?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".GuidelineActivity">
  <androidx.constraintlayout.widget.Guideline
    android:id="@+id/guide"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintGuide_percent="0.5"/>
  <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="确定"
    app:layout_constraintRight_toLeftOf="@id/guide"
    app:layout_constraintTop_toTopOf="parent"
    android:layout_marginRight="50dp"
    android:layout_marginTop="200dp" />
  <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="取消"
    app:layout_constraintLeft_toRightOf="@id/guide"
    app:layout_constraintTop_toTopOf="parent"
    android:layout_marginLeft="50dp"
    android:layout_marginTop="200dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
  1. activity_guideline_2.xml
<?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".GuidelineActivity">
  <androidx.constraintlayout.widget.Guideline
    android:id="@+id/guide"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    app:layout_constraintGuide_percent="0.5" />
  <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="确定"
    app:layout_constraintBottom_toTopOf="@id/guide"
    app:layout_constraintLeft_toLeftOf="parent"
    android:layout_marginBottom="200dp"
    android:layout_marginLeft="200dp" />
  <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="取消"
    app:layout_constraintTop_toBottomOf="@id/guide"
    app:layout_constraintLeft_toLeftOf="parent"
    android:layout_marginTop="200dp"
    android:layout_marginLeft="200dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
  1. activity_guideline_3.xml
<?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".GuidelineActivity">
  <androidx.constraintlayout.widget.Guideline
    android:id="@+id/guide_1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    app:layout_constraintGuide_percent="0.5" />
  <androidx.constraintlayout.widget.Guideline
    android:id="@+id/guide_2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintGuide_percent="0.75" />
  <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="确定"
    app:layout_constraintLeft_toRightOf="@id/guide_2"
    app:layout_constraintBottom_toTopOf="@id/guide_1"
    android:layout_marginBottom="200dp" />
  <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="确定"
    app:layout_constraintLeft_toRightOf="@id/guide_2"
    app:layout_constraintTop_toBottomOf="@id/guide_1"
    android:layout_marginTop="200dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

三、SeekBar

1、基本介绍
  • SeekBar 是 Android 中一个常用的 UI 组件,它允许用户通过拖动滑块来选择一个范围内的值,SeekBar 通常用于音量控制、进度显示等场景,SeekBar 的基本属性如下
属性说明
max设置 SeekBar 的最大值
min设置 SeekBar 的最小值
progress设置或获取 SeekBar 当前进度值
thumb设置或获取滑块的图标
2、演示
(1)Activity Layout
  • activity_seek_bar.xml
<?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".SeekBarActivity">
  <SeekBar
    android:id="@+id/seekBar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:max="100"
    android:progress="50"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
(2)Activity Code
  • SeekBarActivity.java
package com.my.jetpackdemo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.SeekBar;
public class SeekBarActivity
extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_seek_bar);
SeekBar seekBar = findViewById(R.id.seekBar);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// 当进度改变时调用
// fromUser 表示是否由用户操作引起
Log.d("SeekBar", "Progress: " + progress);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// 当用户开始拖动滑块时调用
Log.d("SeekBar", "Start Tracking");
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// 当用户停止拖动滑块时调用
Log.d("SeekBar", "Stop Tracking");
}
});
}
}

四、Chronometer

1、基本介绍
  • Chronometer 是一个计时器控件,它继承自 TextView,并可以通过 1 秒的时间间隔进行计时,并显示出计时结果。这个组件在 Android 开发中可以用于实现对时间的监测,包括开始计时、停止计时、重新计时以及设置计时模式等功能

  • Chronometer 的计时原理相对简单,它内部有一个 Handler 负责定时更新 UI,首先,通过 setBase(long t) 设置好基准时间,当调用 start 方法时,每隔一秒,使用当前的 SystemClock.elapsedRealtime() 减去基准时间,得到的逝去时间就会显示在 TextView 中

  • SystemClock.elapsedRealtime() 是 Android 系统中用于获取系统启动后经过的毫秒数的一个方法,它返回的是一个 long 类型的值,表示从系统启动到现在所经过的时间

2、演示
(1)Activity Layout
  • activity_chronometer_test.xml
<?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".ChronometerTestActivity">
  <Chronometer
    android:id="@+id/chronometer"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textColor="#000000"
    android:textSize="20sp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    tools:ignore="MissingConstraints"
    tools:layout_editor_absoluteY="0dp" />
  <Button
    android:id="@+id/start_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="60dp"
    android:text="Start"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.498"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/chronometer"
    tools:ignore="MissingConstraints" />
  <Button
    android:id="@+id/stop_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="20dp"
    android:text="Stop"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.498"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/start_button"
    tools:ignore="MissingConstraints" />
  <Button
    android:id="@+id/reset_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="20dp"
    android:text="Rest"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.498"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/stop_button"
    tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
(2)Activity Code
  • ChronometerTestActivity.java
package com.my.otherlayout;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.View;
import android.widget.Button;
import android.widget.Chronometer;
public class ChronometerTestActivity
extends AppCompatActivity {
private Chronometer chronometer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chronometer_test);
chronometer = findViewById(R.id.chronometer);
Button startButton = findViewById(R.id.start_button);
Button stopButton = findViewById(R.id.stop_button);
Button resetButton = findViewById(R.id.reset_button);
// 设置基准时间
chronometer.setBase(SystemClock.elapsedRealtime());
startButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
chronometer.start();
}
});
stopButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
chronometer.stop();
}
});
resetButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 重置基准时间,实现重置计时
chronometer.setBase(SystemClock.elapsedRealtime());
chronometer.start();
}
});
}
}

五、RecyclerView

1、基本使用
(1)Entity
  • News.java
package com.my.otherlayout.entity;
public class News
{
public String title;
public String content;
public News(String title, String content) {
this.title = title;
this.content = content;
}
}
(2)Activity Layout
  1. my_recycler_view_demo_item.xml
<?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 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:paddingTop="20dp"
    android:paddingBottom="20dp">
  <TextView
    android:id="@+id/tv_title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginBottom="50dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    tools:text="标题" />
  <TextView
    android:id="@+id/tv_content"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="50dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    tools:text="内容" />
</androidx.constraintlayout.widget.ConstraintLayout>
  1. activity_my_recycler_view_demo.xml
<?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".MyRecyclerViewDemoActivity">
  <LinearLayout
    android:id="@+id/linearLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    tools:layout_editor_absoluteX="1dp"
    tools:layout_editor_absoluteY="1dp"
    tools:ignore="MissingConstraints">
  <Button
    android:id="@+id/btn_add"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginLeft="20dp"
    android:layout_marginRight="10dp"
    android:layout_weight="1"
    android:onClick="addItem"
    android:text="Add" />
  <Button
    android:id="@+id/btn_delete"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginLeft="10dp"
    android:layout_marginRight="20dp"
    android:layout_weight="1"
    android:onClick="deleteItem"
    android:text="Delete" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
  android:id="@+id/rv"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:layout_marginTop="48dp"
  app:layout_constraintTop_toTopOf="parent"
  tools:layout_editor_absoluteX="16dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
(3)Adapter
  • MyRecyclerViewDemoAdapter.java
package com.my.otherlayout.adapter;
import android.annotation.SuppressLint;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.recyclerview.widget.RecyclerView;
import com.my.otherlayout.R;
import com.my.otherlayout.entity.News;
import java.util.List;
public class MyRecyclerViewDemoAdapter
extends RecyclerView.Adapter<
MyRecyclerViewDemoAdapter.MyRecyclerViewDemoViewHolder> {
private Context context;
private List<
News> newsList;
public MyRecyclerViewDemoAdapter(Context context, List<
News> newsList) {
this.context = context;
this.newsList = newsList;
}
@NonNull
@Override
public MyRecyclerViewDemoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = View.inflate(context, R.layout.my_recycler_view_demo_item, null);
MyRecyclerViewDemoViewHolder myRecyclerViewDemoViewHolder = new MyRecyclerViewDemoViewHolder(view);
return myRecyclerViewDemoViewHolder;
}
@Override
public void onBindViewHolder(@NonNull MyRecyclerViewDemoViewHolder holder, @SuppressLint("RecyclerView") int position) {
News news = newsList.get(position);
holder.tvTitle.setText(news.title);
holder.tvContent.setText(news.content);
}
@Override
public int getItemCount() {
return newsList.size();
}
static class MyRecyclerViewDemoViewHolder
extends RecyclerView.ViewHolder {
TextView tvTitle;
TextView tvContent;
ConstraintLayout item;
public MyRecyclerViewDemoViewHolder(@NonNull View itemView) {
super(itemView);
tvTitle = itemView.findViewById(R.id.tv_title);
tvContent = itemView.findViewById(R.id.tv_content);
item = itemView.findViewById(R.id.item);
}
}
}
(4)Activity Code
  • MyRecyclerViewDemoActivity.java
package com.my.otherlayout;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.view.View;
import com.my.otherlayout.adapter.MyRecyclerViewDemoAdapter;
import com.my.otherlayout.entity.News;
import java.util.ArrayList;
import java.util.List;
public class MyRecyclerViewDemoActivity
extends AppCompatActivity {
private RecyclerView rv;
private List<
News> newsList;
private MyRecyclerViewDemoAdapter myRecyclerViewDemoAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_recycler_view_demo);
rv = findViewById(R.id.rv);
newsList = new ArrayList<
>();
for (int i = 0; i <
50; i++) {
News news = new News("标题 " + i, "内容 " + i);
newsList.add(news);
}
myRecyclerViewDemoAdapter = new MyRecyclerViewDemoAdapter(this, newsList);
rv.setAdapter(myRecyclerViewDemoAdapter);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
rv.setLayoutManager(linearLayoutManager);
}
public void addItem(View view) {
News news = new News("标题 新内容", "内容 新内容");
newsList.add(1, news);
myRecyclerViewDemoAdapter.notifyItemInserted(1);
}
public void deleteItem(View view) {
newsList.remove(1);
myRecyclerViewDemoAdapter.notifyItemMoved(0, 1);
}
}
2、高阶应用
(1)布局管理器
  1. LinearLayoutManager 线性布局管理器
// 竖向
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
rv.setLayoutManager(linearLayoutManager);
// 横向
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation(RecyclerView.HORIZONTAL);
rv.setLayoutManager(linearLayoutManager);
  1. StaggeredGridLayoutManager 瀑布流布局管理器
// 竖向
StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
rv.setLayoutManager(staggeredGridLayoutManager);
// 横向
StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.HORIZONTAL);
rv.setLayoutManager(staggeredGridLayoutManager);
  1. GridLayoutManager 网格布局管理器
// 竖向
GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 3);
rv.setLayoutManager(gridLayoutManager);
// 横向
GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 3);
gridLayoutManager.setOrientation(RecyclerView.HORIZONTAL);
rv.setLayoutManager(gridLayoutManager);
(2)Item 分隔线
// 竖向
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
rv.setLayoutManager(linearLayoutManager);
DividerItemDecoration mDivider = new
DividerItemDecoration(this, DividerItemDecoration.VERTICAL);
rv.addItemDecoration(mDivider);
// 横向
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation(RecyclerView.HORIZONTAL);
rv.setLayoutManager(linearLayoutManager);
DividerItemDecoration mDivider = new
DividerItemDecoration(this, DividerItemDecoration.HORIZONTAL);
rv.addItemDecoration(mDivider);
(3)Item 动画
  • RecyclerView 本身具有默认的item动画配置,当动态添加或删除 item 时,RecyclerView 会自动应用这些动画效果,以增强用户体验,不过也可以自定义这些动画
DefaultItemAnimator defaultItemAnimator = new DefaultItemAnimator();
defaultItemAnimator.setAddDuration(1000);
defaultItemAnimator.setRemoveDuration(1000);
rv.setItemAnimator(defaultItemAnimator);
(4)Item 点击
  1. 对整个 Item 文件的根布局添加 id 属性 android:id="@+id/item"

  2. 在适配器中对其绑定点击事件

@Override
public void onBindViewHolder(@NonNull MyRecyclerViewDemoViewHolder holder, @SuppressLint("RecyclerView") int position) {
News news = newsList.get(position);
holder.tvTitle.setText(news.title);
holder.tvContent.setText(news.content);
holder.item.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, "点击了:" + position, Toast.LENGTH_SHORT).show();
}
});
}

六、Toolbar

1、Activity Layout
  • 系统有自带的 Toolbar,想使用自定义的 Toolbar 需要编辑 values/themes.xml 文件,即不使用系统自带的 Toolbar
<resources xmlns:tools="http://schemas.android.com/tools">
  <!-- Base application theme. -->
      <style name="Theme.JetpackDemo" parent="Theme.MaterialComponents.DayNight.NoActionBar">
      ...
    </style>
  </resources>
  • activity_tool_bar_test.xml
<?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".ToolBarTestActivity">
  <androidx.appcompat.widget.Toolbar
    android:id="@+id/tb"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="#ffff00"
    app:layout_constraintTop_toTopOf="parent"
    app:logo="@mipmap/ic_launcher"
    app:navigationIcon="@drawable/arrow_left"
    app:title="Toolbar Test"
    app:titleMarginStart="100dp"
    app:titleTextColor="#ff0000"
    tools:ignore="MissingConstraints"
    tools:layout_editor_absoluteX="0dp" />
  <!-- 标题居中 -->
    <androidx.appcompat.widget.Toolbar
      android:id="@+id/tb_title_center"
      android:layout_width="match_parent"
      android:layout_height="?attr/actionBarSize"
      android:layout_marginTop="80dp"
      android:background="#ffff00"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintHorizontal_bias="0.0"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toBottomOf="@+id/tb"
      app:navigationIcon="@drawable/arrow_left"
      tools:ignore="MissingConstraints">
    <TextView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_gravity="center"
      android:textSize="20dp"
      android:text="Toolbar Test" />
  </androidx.appcompat.widget.Toolbar>
</androidx.constraintlayout.widget.ConstraintLayout>
2、Activity Code
  • ToolBarTestActivity.java
package com.my.otherlayout;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
public class ToolBarTestActivity
extends AppCompatActivity {
public static final String TAG = "ToolBarTestActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tool_bar_test);
Toolbar tb = findViewById(R.id.tb);
tb.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i(TAG, "返回图标被点击了");
}
});
}
}

七、SurfaceView

1、演示
(1)Activity Layout
  • activity_surface_view_test.xml
<?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 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:background="#8BC34A"
    tools:context=".SurfaceViewTestActivity">
  <SurfaceView
    android:id="@+id/sv"
    android:layout_width="300dp"
    android:layout_height="300dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
(2)Activity Code
  • SurfaceViewTestActivity.java
package com.my.otherlayout;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class SurfaceViewTestActivity
extends AppCompatActivity {
private SurfaceView sv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_surface_view_test);
sv = findViewById(R.id.sv);
// 获取 SurfaceHolder,并设置回调
sv.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(@NonNull SurfaceHolder holder) {
// 创建画笔
Paint paint = new Paint();
paint.setColor(Color.RED);
Canvas canvas = null;
try {
// 锁定画布并获取 Canvas 对象
canvas = holder.lockCanvas();
if (canvas != null) {
// 在这里执行绘图操作
// 画布画白
canvas.drawColor(Color.WHITE);
// 绘制一个矩形
canvas.drawRect(50, 50, 200, 200, paint);
}
} finally {
// 无论是否出现异常,都要解锁画布
if (canvas != null) {
holder.unlockCanvasAndPost(canvas);
}
}
}
@Override
public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
// Surface 大小或格式改变时的处理逻辑(可选)
}
@Override
public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
// Surface 销毁时的处理逻辑(可选)
}
});
}
}
2、SurfaceView 简化
(1)SurfaceView
  • MySurfaceView.java
package com.my.otherlayout.surfaceview;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import androidx.annotation.NonNull;
public class MySurfaceView
extends SurfaceView implements SurfaceHolder.Callback {
public MySurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
// 获取 SurfaceHolder,并设置回调
getHolder().addCallback(this);
}
@Override
public void surfaceCreated(@NonNull SurfaceHolder holder) {
// 创建画笔
Paint paint = new Paint();
paint.setColor(Color.RED);
Canvas canvas = null;
try {
// 锁定画布并获取 Canvas 对象
canvas = holder.lockCanvas();
if (canvas != null) {
// 在这里执行绘图操作
// 画布画白
canvas.drawColor(Color.WHITE);
// 绘制一个矩形
canvas.drawRect(50, 50, 200, 200, paint);
}
} finally {
// 无论是否出现异常,都要解锁画布
if (canvas != null) {
holder.unlockCanvasAndPost(canvas);
}
}
}
@Override
public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
}
}
(2)Activity Layout
  • activity_surface_view_simple_test.xml
<?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 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:background="#8BC34A"
    tools:context=".SurfaceViewSimpleTestActivity">
  <com.my.otherlayout.surfaceview.MySurfaceView
    android:id="@+id/sv"
    android:layout_width="300dp"
    android:layout_height="300dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
(3)Activity Code
  • SurfaceViewSimpleTestActivity.java
package com.my.otherlayout;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class SurfaceViewSimpleTestActivity
extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_surface_view_simple_test);
}
}

八、FrameLayout

1、基本介绍
  • FrameLayout 是 Android 中的一个基础布局类,它允许堆叠多个视图在一个屏幕上,并且这些视图会相互覆盖,FrameLayout 中的视图按照它们在布局文件中声明的顺序堆叠,后声明的视图会覆盖先声明的视图
2、演示
<?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
  <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:background="#FF0000"
    android:text="这是第一个 TextView"
    android:textColor="#FFFFFF"
    android:textSize="24sp" />
  <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:background="#00FF00"
    android:text="这是第二个 TextView"
    android:textColor="#FFFFFF"
    android:textSize="24sp"
    android:layout_marginTop="20dp"/>
</FrameLayout>

九、TableLayout

1、基本介绍
  • TableLayout 是 Android 中用于创建表格布局的一个视图组(ViewGroup),它允许以行和列的形式组织子视图,每个 TableRow 对象代表表格中的一行,而每个 TableRow 又可以包含多个视图,这些视图将作为该行中的单元格
2、演示
<?xml version="1.0" encoding="utf-8"?>
    <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:stretchColumns="*">
  <TableRow>
    <TextView
      android:text="姓名"
      android:padding="3dp" />
    <TextView
      android:text="年龄"
      android:padding="3dp" />
  </TableRow>
  <TableRow>
    <TextView
      android:text="张三"
      android:padding="3dp" />
    <TextView
      android:text="25"
      android:padding="3dp" />
  </TableRow>
  <TableRow>
    <TextView
      android:text="李四"
      android:padding="3dp" />
    <TextView
      android:text="30"
      android:padding="3dp" />
  </TableRow>
</TableLayout>

十、AbsoluteLayout

1、基本介绍
  • AbsoluteLayout 是 Android 中一个较旧的布局管理器,它允许您直接指定子视图的 x 和 y 坐标位置,然而,由于 AbsoluteLayout 不支持不同屏幕大小和密度的灵活性,它已经被废弃并在 Android API 级别 3(Android 1.5)之后的版本中被标记为过时,因此,在现代 Android 开发中,不建议使用 AbsoluteLayout
2、演示
<?xml version="1.0" encoding="utf-8"?>
    <AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
  <Button
    android:text="按钮 1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_x="10dp"
    android:layout_y="10dp" />
  <Button
    android:text="按钮 2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_x="100dp"
    android:layout_y="100dp" />
  <TextView
    android:text="这是一个文本视图"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_x="50dp"
    android:layout_y="50dp" />
</AbsoluteLayout>

十一、ProgressBar

1、基本介绍
  • ProgressBar 用于在用户界面中显示一个进度条,以告知用户某个操作正在进行中,ProgressBar 可以是圆形的也可以是水平的,可以通过设置它的样式属性来决定它是圆形的还是水平的
属性说明
max进度条的最大值
progress进度条的初始值
style进度条的样式
样式说明
progressBarStyleSmall小型的圆形进度条
progressBarStyleHorizontal水平的进度条
progressBarStyle-
2、演示
(1)Activity Layout
  • activity_progress_bar_test.xml
<?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".ProgressBarTestActivity">
  <ProgressBar
    android:id="@+id/pb1"
    style="?android:attr/progressBarStyleSmall"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginBottom="40dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent" />
  <ProgressBar
    android:id="@+id/pb2"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginBottom="20dp"
    android:max="100"
    android:progress="50"
    app:layout_constraintBottom_toTopOf="@+id/pb1"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent" />
  <ProgressBar
    android:id="@+id/pb3"
    style="?android:attr/progressBarStyle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginBottom="40dp"
    app:layout_constraintBottom_toTopOf="@+id/pb2"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent" />
  <Button
    android:id="@+id/btn_show"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="40dp"
    android:onClick="show"
    android:text="show"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
  <Button
    android:id="@+id/btn_hide"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="40dp"
    android:onClick="hide"
    android:text="hide"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/btn_show" />
</androidx.constraintlayout.widget.ConstraintLayout>
(2)Activity Code
  • ProgressBarTestActivity.java
package com.my.otherlayout;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ProgressBar;
public class ProgressBarTestActivity
extends AppCompatActivity {
private ProgressBar pb1;
private ProgressBar pb2;
private ProgressBar pb3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_progress_bar_test);
pb1 = findViewById(R.id.pb1);
pb2 = findViewById(R.id.pb2);
pb3 = findViewById(R.id.pb3);
}
public void show(View view) {
pb1.setVisibility(View.VISIBLE);
pb2.setVisibility(View.VISIBLE);
pb3.setVisibility(View.VISIBLE);
}
public void hide(View view) {
pb1.setVisibility(View.GONE);
pb2.setVisibility(View.GONE);
pb3.setVisibility(View.GONE);
}
}

十二、AutoCompleteTextView

1、基本介绍
  • AutoCompleteTextView 控件允许用户输入文本,并自动显示一个下拉列表,这个列表包含了与用户输入匹配的预定义建议
2、演示
(1)Activity Layout
  • activity_auto_complete_text_view_test.xml
<?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".AutoCompleteTextViewTestActivity">
  <AutoCompleteTextView
    android:id="@+id/autoCompleteTextView"
    android:layout_width="200dp"
    android:layout_height="wrap_content"
    android:text=""
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
(2)Activity Code
  • AutoCompleteTextViewTestActivity.java
package com.my.otherlayout;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
public class AutoCompleteTextViewTestActivity
extends AppCompatActivity {
private AutoCompleteTextView autoCompleteTextView;
private String[] suggestions = {
"Apple", "ApApple", "Banana", "BaBanana", "Cherry", "ChCherry"
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_auto_complete_text_view_test);
autoCompleteTextView = findViewById(R.id.autoCompleteTextView);
ArrayAdapter<
String> adapter = new ArrayAdapter<
>(this, android.R.layout.simple_list_item_1, suggestions);
autoCompleteTextView.setAdapter(adapter);
}
}

十三、TextInputLayout

1、基本介绍
  • TextInputLayout 控件提供了一些方式来增强标准的 EditText 控件,提供如下额外的功能和视觉效果
  1. 浮动标签:当 EditText 获得焦点时,标签会浮动到 EditText 的上方,为用户提供一个明确的提示

  2. 错误消息显示:当 EditText 中的输入不满足某些条件时,可以在 TextInputLayout 下方显示一个错误消息

  3. 字符计数:可以显示 EditText 中的字符数,用于限制输入长度的场景

2、演示
(1)Activity Layout
  • activity_text_input_layout_test.xml
<?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".TextInputLayoutTestActivity">
  <com.google.android.material.textfield.TextInputLayout
    android:id="@+id/textInputLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:counterEnabled="true"
    app:counterMaxLength="10"
    app:hintEnabled="true"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintTop_toTopOf="parent">
  <com.google.android.material.textfield.TextInputEditText
    android:id="@+id/textInputEditText"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="请输入内容" />
</com.google.android.material.textfield.TextInputLayout>
<Button
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:onClick="getInputText"
  android:text="获取输入内容"
  app:layout_constraintBottom_toBottomOf="parent"
  app:layout_constraintEnd_toEndOf="parent"
  app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
(2)Activity Code
  • TextInputLayoutTestActivity.java
package com.my.otherlayout;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
public class TextInputLayoutTestActivity
extends AppCompatActivity {
public static final String TAG = TextInputLayoutTestActivity.class.
getSimpleName();
private TextInputLayout textInputLayout;
private TextInputEditText textInputEditText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_text_input_layout_test);
textInputLayout = findViewById(R.id.textInputLayout);
textInputEditText = findViewById(R.id.textInputEditText);
}
public void getInputText(View view) {
// 获取输入内容
String inputText = textInputEditText.getText().toString();
Log.i(TAG, "------------------------------ inputText: " + inputText);
}
}

十四、Chip

1、基本介绍
  • Chip 是 Android 开发中用于表示一个紧凑的、可交互的元素的组件,通常用于表示标签
2、演示
(1)Activity Layout
  • ChipTestActivity.xml
<?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".ChipTestActivity">
  <com.google.android.material.chip.Chip
    android:id="@+id/chip"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="标签"
    android:checkable="true"
    app:chipStrokeWidth="2dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
(2)Activity Code
  • ChipTestActivity.java
package com.my.otherlayout;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.CompoundButton;
import com.google.android.material.chip.Chip;
public class ChipTestActivity
extends AppCompatActivity {
public static final String TAG = ChipTestActivity.class.
getSimpleName();
private Chip chip;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chip_test);
chip = findViewById(R.id.chip);
chip.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i(TAG, "------------------------------ 点击了");
}
});
chip.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Log.i(TAG, "------------------------------ " + (isChecked ? "被选中" : "未被选中"));
}
});
}
}

十五、ChipGroup

1、基本介绍
  • ChipGroup 是 Android 中用于组织和管理多个 Chip 组件的容器,通过将 Chip 放置在 ChipGroup 中,可以更轻松地控制它们的布局和交互行为,ChipGroup 提供了对齐方式、间距等属性,使得多个 Chip 的展示更加整齐和一致
2、演示
(1)Activity Layout
  • activity_chip_group_test.xml
<?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".ChipGroupTestActivity">
  <com.google.android.material.chip.ChipGroup
    android:id="@+id/cg"
    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_toTopOf="parent"
    app:singleSelection="true">
  <com.google.android.material.chip.Chip
    android:id="@+id/chip1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:checkable="true"
    android:text="标签 1" />
  <com.google.android.material.chip.Chip
    android:id="@+id/chip2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:checkable="true"
    android:text="标签 2" />
</com.google.android.material.chip.ChipGroup>
</androidx.constraintlayout.widget.ConstraintLayout>
(2)Activity Code
  • ChipGroupTestActivity.java
package com.my.otherlayout;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import com.google.android.material.chip.Chip;
import com.google.android.material.chip.ChipGroup;
public class ChipGroupTestActivity
extends AppCompatActivity {
public static final String TAG = ChipGroupTestActivity.class.
getSimpleName();
private ChipGroup cg;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chip_group_test);
cg = findViewById(R.id.cg);
cg.setOnCheckedChangeListener(new ChipGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(ChipGroup group, int checkedId) {
for (int i = 0; i < group.getChildCount(); i++) {
Chip chip = (Chip) group.getChildAt(i);
if (chip.getId() == checkedId) {
Log.i(TAG, "------------------------------ 选中了:" + chip.getText());
break;
}
}
}
});
}
}

十五、RadioGroup

1、基本介绍
  • RadioGroup 是 Android 中用于管理多个 RadioButton 组件的容器,它允许用户从一组选项中选择单一选项,确保同一时间只有一个 RadioButton 被选中
2、演示
(1)Activity Layout
  • activity_radio_group_test.xml
<?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".RadioGroupTestActivity">
  <RadioGroup
    android:id="@+id/rg"
    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_toTopOf="parent">
  <RadioButton
    android:id="@+id/rb1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="选项 1" />
  <RadioButton
    android:id="@+id/rb2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="选项 2" />
  <RadioButton
    android:id="@+id/rb3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="选项 3" />
</RadioGroup>
</androidx.constraintlayout.widget.ConstraintLayout>
(2)Activity Code
  • RadioGroupTestActivity.java
package com.my.otherlayout;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.RadioButton;
import android.widget.RadioGroup;
public class RadioGroupTestActivity
extends AppCompatActivity {
public static final String TAG = RadioGroupTestActivity.class.
getSimpleName();
private RadioGroup rg;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_radio_group_test);
rg = findViewById(R.id.rg);
rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
RadioButton rb = findViewById(checkedId);
Log.i(TAG, "------------------------------ 选中了:" + rb.getText());
}
});
}
}
posted @ 2025-08-05 08:37  yjbjingcha  阅读(65)  评论(0)    收藏  举报