一、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());
            }
        });
    }
}
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐