基础使用 - 纵向滚动
添加依赖库
mytest1\build.gradle :
dependencies {
implementation 'androidx.recyclerview:recyclerview:1.1.0'
}
修改xml布局
mytest1\src\main\res\layout\activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/test_rv"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
mytest1\src\main\res\layout\fruit_item.xml : 这个是 RecyclerView 的子项布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/fruit_name_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
/>
<TextView
android:id="@+id/fruit_price_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="20dp"
android:textSize="30sp"
/>
</LinearLayout>
创建Fruit实体类
mytest1\src\main\java\com\example\mytest1\MyFruit.java
public class MyFruit {
private String name;
private float price;
public MyFruit(String name, float price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public float getPrice() {
return price;
}
}
自定义适配器Adapter
mytest1\src\main\java\com\example\mytest1\MyFruitAdapter.java :
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class MyFruitAdapter extends RecyclerView.Adapter<MyFruitAdapter.MyViewHolder> {
private List<MyFruit> mFruitList;
public MyFruitAdapter(List<MyFruit> list) {
this.mFruitList = list;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(
R.layout.fruit_item, parent, false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
MyFruit mFruit = mFruitList.get(position);
holder.mFruitName.setText(mFruit.getName());
holder.mFruitPrice.setText(mFruit.getPrice()+"元");
}
@Override
public int getItemCount() {
return mFruitList.size();
}
static class MyViewHolder extends RecyclerView.ViewHolder {
TextView mFruitName;
TextView mFruitPrice;
public MyViewHolder(View itemView) {
super(itemView);
mFruitName = itemView.findViewById(R.id.fruit_name_tv);
mFruitPrice = itemView.findViewById(R.id.fruit_price_tv);
}
}
}
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.view.Window;
import android.widget.LinearLayout;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
List<MyFruit> mFruitList = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
mFruitList.add(new MyFruit("苹果" + i, (float) (1 + 0.01 * i)));
}
for (int i = 1; i <= 10; i++) {
mFruitList.add(new MyFruit("香蕉" + i, (float) (2 + 0.01 * i)));
}
for (int i = 1; i <= 10; i++) {
mFruitList.add(new MyFruit("橘子" + i, (float) (3 + 0.01 * i)));
}
RecyclerView mRecyclerView = findViewById(R.id.test_rv);
LinearLayoutManager mManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mManager);
MyFruitAdapter mAdapter = new MyFruitAdapter(mFruitList);
mRecyclerView.setAdapter(mAdapter);
}
}
效果
代码示例
地址:GitHub
横向滚动
添加依赖库
mytest2\build.gradle :
dependencies {
implementation 'androidx.recyclerview:recyclerview:1.1.0'
}
修改xml布局
mytest2\src\main\res\layout\activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/test_rv"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
mytest2\src\main\res\layout\fruit_item.xml : 这个是 RecyclerView 的子项布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginLeft="20dp"
android:background="#ff0"
>
<TextView
android:id="@+id/fruit_name_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
/>
<TextView
android:id="@+id/fruit_price_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
/>
</LinearLayout>
创建Fruit实体类
mytest2\src\main\java\com\example\mytest2\MyFruit.java
public class MyFruit {
private String name;
private float price;
public MyFruit(String name, float price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public float getPrice() {
return price;
}
}
自定义适配器Adapter
mytest2\src\main\java\com\example\mytest2\MyFruitAdapter.java :
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class MyFruitAdapter extends RecyclerView.Adapter<MyFruitAdapter.MyViewHolder> {
private List<MyFruit> mFruitList;
public MyFruitAdapter(List<MyFruit> list) {
this.mFruitList = list;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(
R.layout.fruit_item, parent, false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
MyFruit mFruit = mFruitList.get(position);
holder.mFruitName.setText(mFruit.getName());
holder.mFruitPrice.setText(mFruit.getPrice()+"元");
}
@Override
public int getItemCount() {
return mFruitList.size();
}
static class MyViewHolder extends RecyclerView.ViewHolder {
TextView mFruitName;
TextView mFruitPrice;
public MyViewHolder(View itemView) {
super(itemView);
mFruitName = itemView.findViewById(R.id.fruit_name_tv);
mFruitPrice = itemView.findViewById(R.id.fruit_price_tv);
}
}
}
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.view.Window;
import android.widget.LinearLayout;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
List<MyFruit> mFruitList = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
mFruitList.add(new MyFruit("苹果" + i, (float) (1 + 0.01 * i)));
}
for (int i = 1; i <= 10; i++) {
mFruitList.add(new MyFruit("香蕉" + i, (float) (2 + 0.01 * i)));
}
for (int i = 1; i <= 10; i++) {
mFruitList.add(new MyFruit("橘子" + i, (float) (3 + 0.01 * i)));
}
RecyclerView mRecyclerView = findViewById(R.id.test_rv);
LinearLayoutManager mManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mManager);
MyFruitAdapter mAdapter = new MyFruitAdapter(mFruitList);
mRecyclerView.setAdapter(mAdapter);
}
}
效果
代码示例
地址:GitHub
瀑布流布局
添加依赖库
mytest2\build.gradle :
dependencies {
implementation 'androidx.recyclerview:recyclerview:1.1.0'
}
修改xml布局
mytest3\src\main\res\layout\activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/test_rv"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
mytest3\src\main\res\layout\fruit_item.xml : 这个是 RecyclerView 的子项布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_margin="5dp"
android:background="#FF44FF"
>
<TextView
android:id="@+id/fruit_name_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
/>
<TextView
android:id="@+id/fruit_content_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:layout_gravity="left"
android:layout_marginTop="10dp"
/>
</LinearLayout>
创建Fruit实体类
mytest3\src\main\java\com\example\mytest3\MyFruit.java
public class MyFruit {
private String name;
private String content;
public MyFruit(String name, String content) {
this.name = name;
this.content = content;
}
public String getName() {
return name;
}
public String getContent() {
return content;
}
}
自定义适配器Adapter
mytest3\src\main\java\com\example\mytest3\MyFruitAdapter.java :
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class MyFruitAdapter extends RecyclerView.Adapter<MyFruitAdapter.MyViewHolder> {
private List<MyFruit> mFruitList;
public MyFruitAdapter(List<MyFruit> list) {
this.mFruitList = list;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(
R.layout.fruit_item, parent, false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
MyFruit mFruit = mFruitList.get(position);
holder.mFruitName.setText(mFruit.getName());
holder.mFruitContent.setText(mFruit.getContent());
}
@Override
public int getItemCount() {
return mFruitList.size();
}
static class MyViewHolder extends RecyclerView.ViewHolder {
TextView mFruitName;
TextView mFruitContent;
public MyViewHolder(View itemView) {
super(itemView);
mFruitName = itemView.findViewById(R.id.fruit_name_tv);
mFruitContent = itemView.findViewById(R.id.fruit_content_tv);
}
}
}
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import android.view.Window;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
List<MyFruit> mFruitList = new ArrayList<>();
for (int i = 1; i <= 15; i++) {
StringBuilder builder = new StringBuilder();
for (int j = 0; j < new Random().nextInt(10) + 1; j++){
builder.append("苹果");
}
mFruitList.add(new MyFruit("苹果" + i, builder.toString()));
}
for (int i = 1; i <= 15; i++) {
StringBuilder builder = new StringBuilder();
for (int j = 0; j < new Random().nextInt(10) + 1; j++){
builder.append("香蕉");
}
mFruitList.add(new MyFruit("香蕉" + i, builder.toString()));
}
for (int i = 1; i <= 15; i++) {
StringBuilder builder = new StringBuilder();
for (int j = 0; j < new Random().nextInt(10) + 1; j++){
builder.append("橘子");
}
mFruitList.add(new MyFruit("橘子" + i, builder.toString()));
}
RecyclerView mRecyclerView = findViewById(R.id.test_rv);
StaggeredGridLayoutManager mManager = new
StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(mManager);
MyFruitAdapter mAdapter = new MyFruitAdapter(mFruitList);
mRecyclerView.setAdapter(mAdapter);
}
}
效果
代码示例
地址:GitHub
点击事件
添加依赖库
mytest4\build.gradle :
dependencies {
implementation 'androidx.recyclerview:recyclerview:1.1.0'
}
修改xml布局
mytest4\src\main\res\layout\activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/test_rv"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
mytest4\src\main\res\layout\fruit_item.xml : 这个是 RecyclerView 的子项布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/fruit_name_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
/>
<TextView
android:id="@+id/fruit_price_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="20dp"
android:textSize="30sp"
/>
</LinearLayout>
创建Fruit实体类
mytest4\src\main\java\com\example\mytest4\MyFruit.java
public class MyFruit {
private String name;
private float price;
public MyFruit(String name, float price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public float getPrice() {
return price;
}
}
自定义适配器Adapter
mytest4\src\main\java\com\example\mytest4\MyFruitAdapter.java :
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class MyFruitAdapter extends RecyclerView.Adapter<MyFruitAdapter.MyViewHolder> {
private List<MyFruit> mFruitList;
public MyFruitAdapter(List<MyFruit> list) {
this.mFruitList = list;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(
R.layout.fruit_item, parent, false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
MyFruit mFruit = mFruitList.get(position);
holder.mFruitName.setText(mFruit.getName());
holder.mFruitPrice.setText(mFruit.getPrice()+"元");
}
@Override
public int getItemCount() {
return mFruitList.size();
}
static class MyViewHolder extends RecyclerView.ViewHolder {
TextView mFruitName;
TextView mFruitPrice;
public MyViewHolder(View itemView) {
super(itemView);
mFruitName = itemView.findViewById(R.id.fruit_name_tv);
mFruitPrice = itemView.findViewById(R.id.fruit_price_tv);
}
}
}
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.view.Window;
import android.widget.LinearLayout;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
List<MyFruit> mFruitList = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
mFruitList.add(new MyFruit("苹果" + i, (float) (1 + 0.01 * i)));
}
for (int i = 1; i <= 10; i++) {
mFruitList.add(new MyFruit("香蕉" + i, (float) (2 + 0.01 * i)));
}
for (int i = 1; i <= 10; i++) {
mFruitList.add(new MyFruit("橘子" + i, (float) (3 + 0.01 * i)));
}
RecyclerView mRecyclerView = findViewById(R.id.test_rv);
LinearLayoutManager mManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mManager);
MyFruitAdapter mAdapter = new MyFruitAdapter(mFruitList);
mRecyclerView.setAdapter(mAdapter);
}
}
效果
代码示例
地址:GitHub
分割线1 - 在适配器 onCreateViewHolder 中设置
在 Adapter 的 onCreateViewHolder 方法中进行设置 margin,以达到分割线的效果。
添加依赖库
mytest5\build.gradle :
dependencies {
implementation 'androidx.recyclerview:recyclerview:1.1.0'
}
修改xml布局
mytest5\src\main\res\layout\activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/test_rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
/>
</LinearLayout>
mytest5\src\main\res\layout\fruit_item.xml : 这个是 RecyclerView 的子项布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#9D9D9D"
>
<TextView
android:id="@+id/fruit_name_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="30sp"
android:gravity="center"
/>
<TextView
android:id="@+id/fruit_price_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingLeft="20dp"
android:textSize="30sp"
android:gravity="center"
/>
</LinearLayout>
创建Fruit实体类
mytest5\src\main\java\com\example\mytest5\MyFruit.java
public class MyFruit {
private String name;
private float price;
public MyFruit(String name, float price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public float getPrice() {
return price;
}
}
自定义适配器Adapter
mytest5\src\main\java\com\example\mytest5\MyFruitAdapter.java :
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class MyFruitAdapter extends RecyclerView.Adapter<MyFruitAdapter.MyViewHolder> {
private List<MyFruit> mFruitList;
public MyFruitAdapter(List<MyFruit> list) {
this.mFruitList = list;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(
R.layout.fruit_item, parent, false);
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
layoutParams.topMargin = 1;
view.setLayoutParams(layoutParams);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
MyFruit mFruit = mFruitList.get(position);
holder.mFruitName.setText(mFruit.getName());
holder.mFruitPrice.setText(mFruit.getPrice()+"元");
}
@Override
public int getItemCount() {
return mFruitList.size();
}
static class MyViewHolder extends RecyclerView.ViewHolder {
TextView mFruitName;
TextView mFruitPrice;
public MyViewHolder(View itemView) {
super(itemView);
mFruitName = itemView.findViewById(R.id.fruit_name_tv);
mFruitPrice = itemView.findViewById(R.id.fruit_price_tv);
}
}
}
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.view.Window;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
List<MyFruit> mFruitList = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
mFruitList.add(new MyFruit("苹果" + i, (float) (1 + 0.01 * i)));
}
for (int i = 1; i <= 10; i++) {
mFruitList.add(new MyFruit("香蕉" + i, (float) (2 + 0.01 * i)));
}
for (int i = 1; i <= 10; i++) {
mFruitList.add(new MyFruit("橘子" + i, (float) (3 + 0.01 * i)));
}
RecyclerView mRecyclerView = findViewById(R.id.test_rv);
LinearLayoutManager mManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mManager);
MyFruitAdapter mAdapter = new MyFruitAdapter(mFruitList);
mRecyclerView.setAdapter(mAdapter);
}
}
效果
代码示例
地址:GitHub
分割线2 - 在 ItemDecoration 中 getItemOffsets 设置 rect
???? 在自定义 ItemDecoration 中,在 getItemOffsets 方法中 设置 rect,设置后,会露出底色,就是背景色,颜色也就取决于背景色了。
添加依赖库
mytest6\build.gradle :
dependencies {
implementation 'androidx.recyclerview:recyclerview:1.1.0'
}
修改xml布局
mytest6\src\main\res\layout\activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/test_rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
/>
</LinearLayout>
mytest6\src\main\res\layout\fruit_item.xml : 这个是 RecyclerView 的子项布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#9D9D9D"
>
<TextView
android:id="@+id/fruit_name_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="30sp"
android:gravity="center"
/>
<TextView
android:id="@+id/fruit_price_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingLeft="20dp"
android:textSize="30sp"
android:gravity="center"
/>
</LinearLayout>
创建Fruit实体类
mytest6\src\main\java\com\example\mytest6\MyFruit.java
public class MyFruit {
private String name;
private float price;
public MyFruit(String name, float price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public float getPrice() {
return price;
}
}
自定义适配器Adapter
mytest6\src\main\java\com\example\mytest6\MyFruitAdapter.java :
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class MyFruitAdapter extends RecyclerView.Adapter<MyFruitAdapter.MyViewHolder> {
private List<MyFruit> mFruitList;
public MyFruitAdapter(List<MyFruit> list) {
this.mFruitList = list;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(
R.layout.fruit_item, parent, false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
MyFruit mFruit = mFruitList.get(position);
holder.mFruitName.setText(mFruit.getName());
holder.mFruitPrice.setText(mFruit.getPrice()+"元");
}
@Override
public int getItemCount() {
return mFruitList.size();
}
static class MyViewHolder extends RecyclerView.ViewHolder {
TextView mFruitName;
TextView mFruitPrice;
public MyViewHolder(View itemView) {
super(itemView);
mFruitName = itemView.findViewById(R.id.fruit_name_tv);
mFruitPrice = itemView.findViewById(R.id.fruit_price_tv);
}
}
}
自定义ItemDecoration
import android.graphics.Rect;
import android.view.View;
import androidx.recyclerview.widget.RecyclerView;
public class MyItemDecoration extends RecyclerView.ItemDecoration {
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
outRect.set(0, 1, 0, 0);
}
}
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.view.Window;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
List<MyFruit> mFruitList = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
mFruitList.add(new MyFruit("苹果" + i, (float) (1 + 0.01 * i)));
}
for (int i = 1; i <= 10; i++) {
mFruitList.add(new MyFruit("香蕉" + i, (float) (2 + 0.01 * i)));
}
for (int i = 1; i <= 10; i++) {
mFruitList.add(new MyFruit("橘子" + i, (float) (3 + 0.01 * i)));
}
RecyclerView mRecyclerView = findViewById(R.id.test_rv);
LinearLayoutManager mManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mManager);
MyFruitAdapter mAdapter = new MyFruitAdapter(mFruitList);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.addItemDecoration(new MyItemDecoration());
}
}
效果
代码示例
地址:GitHub
分割线3 - getItemOffsets、onDraw、onDrawOver
???? 在自定义 ItemDecoration 中,在 getItemOffsets 方法中 设置 rect,设置后,会露出底色,就是背景色,颜色也就取决于背景色了; ???? 然后在 onDraw 方法 或 onDrawOver 方法中,再在 rect 区域再次绘制一个 rect。
添加依赖库
mytest7\build.gradle :
dependencies {
implementation 'androidx.recyclerview:recyclerview:1.1.0'
}
修改xml布局
mytest7\src\main\res\layout\activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/test_rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
android:padding="10dp"
/>
</LinearLayout>
mytest7\src\main\res\layout\fruit_item.xml : 这个是 RecyclerView 的子项布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#9D9D9D"
>
<TextView
android:id="@+id/fruit_name_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="30sp"
android:gravity="center"
/>
<TextView
android:id="@+id/fruit_price_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingLeft="20dp"
android:textSize="30sp"
android:gravity="center"
/>
</LinearLayout>
创建Fruit实体类
mytest7\src\main\java\com\example\mytest7\MyFruit.java
public class MyFruit {
private String name;
private float price;
public MyFruit(String name, float price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public float getPrice() {
return price;
}
}
自定义适配器Adapter
mytest7\src\main\java\com\example\mytest7\MyFruitAdapter.java :
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class MyFruitAdapter extends RecyclerView.Adapter<MyFruitAdapter.MyViewHolder> {
private List<MyFruit> mFruitList;
public MyFruitAdapter(List<MyFruit> list) {
this.mFruitList = list;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(
R.layout.fruit_item, parent, false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
MyFruit mFruit = mFruitList.get(position);
holder.mFruitName.setText(mFruit.getName());
holder.mFruitPrice.setText(mFruit.getPrice()+"元");
}
@Override
public int getItemCount() {
return mFruitList.size();
}
static class MyViewHolder extends RecyclerView.ViewHolder {
TextView mFruitName;
TextView mFruitPrice;
public MyViewHolder(View itemView) {
super(itemView);
mFruitName = itemView.findViewById(R.id.fruit_name_tv);
mFruitPrice = itemView.findViewById(R.id.fruit_price_tv);
}
}
}
自定义ItemDecoration
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public class MyItemDecoration extends RecyclerView.ItemDecoration {
private int mDividerHeight;
@Override
public void getItemOffsets(Rect outRect, View view,
RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
mDividerHeight = 2;
outRect.set(0, mDividerHeight, 0, 0);
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
Paint mPaint = new Paint();
mPaint.setColor(Color.RED);
for (int i = 0; i < parent.getChildCount(); i++) {
View view = parent.getChildAt(i);
int index = parent.getChildAdapterPosition(view);
if (index == 0) {
continue;
}
float mLeft = parent.getPaddingLeft();
float mTop = view.getTop() - mDividerHeight;
float mRight = parent.getWidth() - parent.getPaddingRight();
float mBottom = view.getTop();
c.drawRect(mLeft, mTop, mRight, mBottom, mPaint);
}
}
}
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.view.Window;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
List<MyFruit> mFruitList = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
mFruitList.add(new MyFruit("苹果" + i, (float) (1 + 0.01 * i)));
}
for (int i = 1; i <= 10; i++) {
mFruitList.add(new MyFruit("香蕉" + i, (float) (2 + 0.01 * i)));
}
for (int i = 1; i <= 10; i++) {
mFruitList.add(new MyFruit("橘子" + i, (float) (3 + 0.01 * i)));
}
RecyclerView mRecyclerView = findViewById(R.id.test_rv);
LinearLayoutManager mManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mManager);
MyFruitAdapter mAdapter = new MyFruitAdapter(mFruitList);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.addItemDecoration(new MyItemDecoration());
}
}
效果
代码示例
地址:GitHub
分割线4 - 实现每个分组都有一个头部分割线
添加依赖库
mytest8\build.gradle :
dependencies {
implementation 'androidx.recyclerview:recyclerview:1.1.0'
}
修改xml布局
mytest8\src\main\res\layout\activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/test_rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
android:paddingTop="100dp"
/>
</LinearLayout>
mytest8\src\main\res\layout\fruit_item.xml : 这个是 RecyclerView 的子项布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#9D9D9D"
>
<TextView
android:id="@+id/fruit_name_tv"
android:layout_width="wrap_content"
android:layout_height="60dp"
android:layout_weight="1"
android:textSize="20sp"
android:textColor="#90EE90"
android:gravity="center"
/>
<TextView
android:id="@+id/fruit_price_tv"
android:layout_width="wrap_content"
android:layout_height="60dp"
android:layout_weight="1"
android:paddingLeft="20dp"
android:textSize="20sp"
android:textColor="#90EE90"
android:gravity="center"
/>
</LinearLayout>
创建Fruit实体类
mytest8\src\main\java\com\example\mytest8\MyFruit.java
public class MyFruit {
private String group;
private String name;
private float price;
public MyFruit(String group, String name, float price) {
this.group = group;
this.name = name;
this.price = price;
}
public String getGroup() {
return group;
}
public String getName() {
return name;
}
public float getPrice() {
return price;
}
}
自定义适配器Adapter
mytest8\src\main\java\com\example\mytest8\MyFruitAdapter.java :
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class MyFruitAdapter extends RecyclerView.Adapter<MyFruitAdapter.MyViewHolder> {
private List<MyFruit> mFruitList;
public MyFruitAdapter(List<MyFruit> list) {
this.mFruitList = list;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(
R.layout.fruit_item, parent, false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
MyFruit mFruit = mFruitList.get(position);
holder.mFruitName.setText(mFruit.getName());
holder.mFruitPrice.setText(mFruit.getPrice()+"元");
}
@Override
public int getItemCount() {
return mFruitList.size();
}
static class MyViewHolder extends RecyclerView.ViewHolder {
TextView mFruitName;
TextView mFruitPrice;
public MyViewHolder(View itemView) {
super(itemView);
mFruitName = itemView.findViewById(R.id.fruit_name_tv);
mFruitPrice = itemView.findViewById(R.id.fruit_price_tv);
}
}
public boolean isGroupFirst(int position) {
if (position == 0) {
return true;
} else {
String currentGroupName = getGroupName(position);
String preGroupName = mFruitList.get(position - 1).getGroup();
if (currentGroupName.equals(preGroupName)) {
return false;
} else {
return true;
}
}
}
public String getGroupName(int position) {
return mFruitList.get(position).getGroup();
}
}
自定义ItemDecoration
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.Log;
import android.view.View;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
public class MyItemDecoration extends RecyclerView.ItemDecoration {
private static final String TAG = "AAAAAAAAAA";
private int mHeadHeight;
Paint textPaint;
Rect textRect;
Paint headPaint;
public MyItemDecoration(Context context) {
mHeadHeight = dp2px(context, 100);
textPaint = new Paint();
textPaint.setTextSize(50);
textPaint.setColor(Color.WHITE);
textRect = new Rect();
headPaint = new Paint();
headPaint.setColor(Color.RED);
}
@Override
public void getItemOffsets(Rect outRect, View view,
RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
if (parent.getAdapter() instanceof MyFruitAdapter) {
MyFruitAdapter adapter = (MyFruitAdapter) parent.getAdapter();
int position = parent.getChildAdapterPosition(view);
Log.d(TAG, "getItemOffsets position: " + position);
if (adapter.isGroupFirst(position)) {
outRect.set(0, mHeadHeight, 0, 0);
} else {
outRect.set(0, 2, 0, 0);
}
}
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
if (parent.getAdapter() instanceof MyFruitAdapter) {
MyFruitAdapter adapter = (MyFruitAdapter) parent.getAdapter();
int childCount = parent.getChildCount();
int mLeft = parent.getPaddingLeft();
int mRight = parent.getWidth() - parent.getPaddingRight();
for (int i = 0; i < childCount; i++) {
View view = parent.getChildAt(i);
int position = parent.getChildAdapterPosition(view);
Log.d(TAG, "onDraw position: " + position);
String groupName = adapter.getGroupName(position);
if (adapter.isGroupFirst(position) && view.getTop() - parent.getPaddingTop() >= mHeadHeight) {
c.drawRect( mLeft, view.getTop() - mHeadHeight, mRight, view.getTop(), headPaint);
textPaint.getTextBounds(groupName, 0, groupName.length(), textRect);
c.drawText(groupName, mLeft, view.getTop() - mHeadHeight/2 + textRect.height()/2, textPaint);
} else if (view.getTop() - parent.getPaddingTop() >= mHeadHeight) {
c.drawRect( mLeft, view.getTop() - 2, mRight, view.getTop(), headPaint);
}
}
}
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
if (parent.getAdapter() instanceof MyFruitAdapter) {
MyFruitAdapter adapter = (MyFruitAdapter) parent.getAdapter();
int position = ((LinearLayoutManager) parent.getLayoutManager()).findFirstVisibleItemPosition();
View itemView = parent.findViewHolderForAdapterPosition(position).itemView;
int mLeft = parent.getPaddingLeft();
int mTop = parent.getPaddingTop();
int mRight = parent.getWidth() - parent.getPaddingRight();
if (adapter.isGroupFirst(position+1)) {
int mTempHeight = Math.min(mHeadHeight, itemView.getBottom() - parent.getPaddingTop());
c.drawRect(mLeft, mTop, mRight, mTop + mTempHeight, headPaint);
String groupName = adapter.getGroupName(position);
textPaint.getTextBounds(groupName, 0, groupName.length(), textRect);
c.clipRect(mLeft, mTop, mRight, mTop + mTempHeight);
c.drawText(groupName, mLeft, mTop + mTempHeight - mHeadHeight/2 + textRect.height()/2, textPaint);
} else {
c.drawRect(mLeft, mTop, mRight, mTop + mHeadHeight, headPaint);
String groupName = adapter.getGroupName(position);
textPaint.getTextBounds(groupName, 0, groupName.length(), textRect);
c.drawText(groupName, mLeft, mTop + mHeadHeight/2 + textRect.height()/2, textPaint);
}
}
}
private int dp2px(Context context, float dpValue) {
float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale * 0.5f);
}
}
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.view.Window;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
List<MyFruit> mFruitList = new ArrayList<>();
for (int i = 1; i <= 20; i++) {
mFruitList.add(new MyFruit("苹果", "苹果" + i, (float) (1 + 0.01 * i)));
}
for (int i = 1; i <= 20; i++) {
mFruitList.add(new MyFruit("香蕉", "香蕉" + i, (float) (2 + 0.01 * i)));
}
for (int i = 1; i <= 20; i++) {
mFruitList.add(new MyFruit("橘子", "橘子" + i, (float) (3 + 0.01 * i)));
}
RecyclerView mRecyclerView = findViewById(R.id.test_rv);
LinearLayoutManager mManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mManager);
MyFruitAdapter mAdapter = new MyFruitAdapter(mFruitList);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.addItemDecoration(new MyItemDecoration(this));
}
}
效果
代码示例
地址:GitHub
自定义LayoutManager
添加依赖库
mytest9\build.gradle :
dependencies {
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'com.github.bumptech.glide:glide:4.11.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
}
修改xml布局
mytest9\src\main\res\layout\activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/test_rv"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
mytest9\src\main\res\layout\pic_item.xml : 这个是 RecyclerView 的子项布局
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="260dp"
android:layout_height="360dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:foreground="?android:attr/selectableItemBackground"
app:cardBackgroundColor="@color/teal_200">
<ImageView
android:id="@+id/pic_id_iv"
android:layout_width="200dp"
android:layout_height="300dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:src="@mipmap/ic_launcher"/>
<TextView
android:id="@+id/pic_name_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="310dp"
android:paddingTop="10dp"
android:text="name"/>
<TextView
android:id="@+id/pic_position_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|bottom"
android:layout_margin="3dp"
android:textColor="@android:color/white"
android:text="1/10"
/>
</androidx.cardview.widget.CardView>
创建MyPicBean实体类
mytest9\src\main\java\com\example\mytest9\MyPicBean.java
public class MyPicBean {
private int pic_id;
private String pic_name;
private int pic_position;
public MyPicBean(int pic_id, String pic_name, int pic_position) {
this.pic_id = pic_id;
this.pic_name = pic_name;
this.pic_position = pic_position;
}
public int getPic_id() {
return pic_id;
}
public void setPic_id(int pic_id) {
this.pic_id = pic_id;
}
public String getPic_name() {
return pic_name;
}
public void setPic_name(String pic_name) {
this.pic_name = pic_name;
}
public int getPic_position() {
return pic_position;
}
public void setPic_position(int pic_position) {
this.pic_position = pic_position;
}
}
自定义适配器Adapter
mytest9\src\main\java\com\example\mytest9\MyPicAdapter.java :
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import java.util.List;
public class MyPicAdapter extends RecyclerView.Adapter<MyPicAdapter.MyViewHolder> {
private List<MyPicBean> mPicBeanList;
Context context;
public MyPicAdapter(Context context, List<MyPicBean> list) {
this.context = context;
this.mPicBeanList = list;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(
R.layout.pic_item, parent, false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
MyPicBean mPicBean = mPicBeanList.get(position);
int mTotal = mPicBeanList == null ? 0 : mPicBeanList.size();
Glide.with(context).load(mPicBean.getPic_id()).into(holder.pic_id_iv);
holder.pic_name_tv.setText(mPicBean.getPic_name());
holder.pic_position_tv.setText(mPicBean.getPic_position()+"/" + mTotal);
}
@Override
public int getItemCount() {
return mPicBeanList == null ? 0 : mPicBeanList.size();
}
static class MyViewHolder extends RecyclerView.ViewHolder{
ImageView pic_id_iv;
TextView pic_name_tv;
TextView pic_position_tv;
public MyViewHolder(View itemView) {
super(itemView);
pic_id_iv = itemView.findViewById(R.id.pic_id_iv);
pic_name_tv = itemView.findViewById(R.id.pic_name_tv);
pic_position_tv = itemView.findViewById(R.id.pic_position_tv);
}
}
}
自定义LayoutManager
mytest9\src\main\java\com\example\mytest9\MyLayoutManager.java :
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import androidx.recyclerview.widget.RecyclerView;
public class MyLayoutManager extends RecyclerView.LayoutManager {
private static final String TAG = "AAAAAAA";
@Override
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
detachAndScrapAttachedViews(recycler);
int itemCount = getItemCount();
Log.d(TAG, "itemCount: " +itemCount);
for (int i=0; i < itemCount; i++) {
View view = recycler.getViewForPosition(i);
addView(view);
measureChildWithMargins(view, 0, 0);
int widthSpace = getWidth() - getDecoratedMeasuredWidth(view);
int heightSpace = getHeight() - getDecoratedMeasuredHeight(view);
layoutDecoratedWithMargins(view,
widthSpace/2,
heightSpace/2,
widthSpace/2 + getDecoratedMeasuredWidth(view),
heightSpace/2 + getDecoratedMeasuredHeight(view)
);
view.setTranslationY(10 * (itemCount -i));
view.setTranslationX(10 * (itemCount -i));
}
}
}
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.view.Window;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
List<MyPicBean> mPicList = new ArrayList<>();
for (int i = 1; i <= 9; i++) {
mPicList.add(new MyPicBean(R.drawable.ic_launcher_background, "图" + i, i));
}
RecyclerView mRecyclerView = findViewById(R.id.test_rv);
MyLayoutManager mManager = new MyLayoutManager();
mRecyclerView.setLayoutManager(mManager);
MyPicAdapter mAdapter = new MyPicAdapter(this, mPicList);
mRecyclerView.setAdapter(mAdapter);
}
}
效果
代码示例
地址:GitHub
自定义ItemTouchHelper.SimpleCallback
添加依赖库
mytest10\build.gradle :
dependencies {
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'com.github.bumptech.glide:glide:4.11.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
}
修改xml布局
mytest10\src\main\res\layout\activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/test_rv"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
mytest10\src\main\res\layout\pic_item.xml : 这个是 RecyclerView 的子项布局
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="260dp"
android:layout_height="360dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:foreground="?android:attr/selectableItemBackground"
app:cardBackgroundColor="@color/teal_200"
android:clickable="true"
>
<ImageView
android:id="@+id/pic_id_iv"
android:layout_width="200dp"
android:layout_height="300dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:src="@mipmap/ic_launcher"/>
<TextView
android:id="@+id/pic_name_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="310dp"
android:paddingTop="10dp"
android:text="name"/>
<TextView
android:id="@+id/pic_position_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|bottom"
android:paddingRight="20dp"
android:paddingBottom="20dp"
android:layout_margin="3dp"
android:textColor="@android:color/white"
android:text="1/10"
/>
</androidx.cardview.widget.CardView>
创建MyPicBean实体类
mytest10\src\main\java\com\example\mytest10\MyPicBean.java
public class MyPicBean {
private int pic_id;
private String pic_name;
private int pic_position;
public MyPicBean(int pic_id, String pic_name, int pic_position) {
this.pic_id = pic_id;
this.pic_name = pic_name;
this.pic_position = pic_position;
}
public int getPic_id() {
return pic_id;
}
public void setPic_id(int pic_id) {
this.pic_id = pic_id;
}
public String getPic_name() {
return pic_name;
}
public void setPic_name(String pic_name) {
this.pic_name = pic_name;
}
public int getPic_position() {
return pic_position;
}
public void setPic_position(int pic_position) {
this.pic_position = pic_position;
}
}
自定义适配器Adapter
mytest10\src\main\java\com\example\mytest10\MyPicAdapter.java :
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import java.util.List;
public class MyPicAdapter extends RecyclerView.Adapter<MyPicAdapter.MyViewHolder> {
private List<MyPicBean> mPicBeanList;
Context context;
public MyPicAdapter(Context context, List<MyPicBean> list) {
this.context = context;
this.mPicBeanList = list;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(
R.layout.pic_item, parent, false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
MyPicBean mPicBean = mPicBeanList.get(position);
int mTotal = mPicBeanList == null ? 0 : mPicBeanList.size();
Glide.with(context).load(mPicBean.getPic_id()).into(holder.pic_id_iv);
holder.pic_name_tv.setText(mPicBean.getPic_name());
holder.pic_position_tv.setText(mPicBean.getPic_position()+"/" + mTotal);
}
@Override
public int getItemCount() {
return mPicBeanList == null ? 0 : mPicBeanList.size();
}
static class MyViewHolder extends RecyclerView.ViewHolder{
ImageView pic_id_iv;
TextView pic_name_tv;
TextView pic_position_tv;
public MyViewHolder(View itemView) {
super(itemView);
pic_id_iv = itemView.findViewById(R.id.pic_id_iv);
pic_name_tv = itemView.findViewById(R.id.pic_name_tv);
pic_position_tv = itemView.findViewById(R.id.pic_position_tv);
}
}
}
自定义LayoutManager
mytest10\src\main\java\com\example\mytest10\MyLayoutManager.java :
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import androidx.recyclerview.widget.RecyclerView;
public class MyLayoutManager extends RecyclerView.LayoutManager {
private static final String TAG = "AAAAAAA";
public static final int showCount = 4;
@Override
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
detachAndScrapAttachedViews(recycler);
int itemCount = getItemCount();
Log.d(TAG, "itemCount: " +itemCount);
int bottomPosition;
if (itemCount < showCount) {
bottomPosition = 0;
} else {
bottomPosition = itemCount - showCount;
}
for (int i=bottomPosition; i < itemCount; i++) {
View view = recycler.getViewForPosition(i);
addView(view);
measureChildWithMargins(view, 0, 0);
int widthSpace = getWidth() - getDecoratedMeasuredWidth(view);
int heightSpace = getHeight() - getDecoratedMeasuredHeight(view);
layoutDecoratedWithMargins(view,
widthSpace/2,
heightSpace/2,
widthSpace/2 + getDecoratedMeasuredWidth(view),
heightSpace/2 + getDecoratedMeasuredHeight(view)
);
int level = itemCount - i - 1;
if (level > 0) {
if (level < showCount - 1) {
view.setTranslationY(40 * level);
view.setTranslationX(40 * level);
} else {
view.setTranslationY(40 * (level-1));
view.setTranslationX(40 * (level-1));
}
}
}
}
}
自定义ItemTouchHelper.SimpleCallback
mytest10\src\main\java\com\example\mytest10\MyItemTouchHelperCallback.java
import android.graphics.Canvas;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class MyItemTouchHelperCallback extends ItemTouchHelper.SimpleCallback {
private static final String TAG = "AAAAAA";
private RecyclerView recyclerView;
private MyPicAdapter adapter;
private List<MyPicBean> mDatas;
public MyItemTouchHelperCallback(RecyclerView recyclerView, MyPicAdapter adapter, List<MyPicBean> mDatas) {
super(0, 15);
this.recyclerView = recyclerView;
this.adapter = adapter;
this.mDatas = mDatas;
}
@Override
public boolean onMove(@NonNull RecyclerView recyclerView,
@NonNull RecyclerView.ViewHolder viewHolder,
@NonNull RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
MyPicBean picBean = mDatas.remove(viewHolder.getLayoutPosition());
mDatas.add(0, picBean);
adapter.notifyDataSetChanged();
Log.d(TAG, "notifyDataSetChanged: ");
}
@Override
public long getAnimationDuration(@NonNull RecyclerView recyclerView,
int animationType, float animateDx, float animateDy) {
return 1000;
}
@Override
public float getSwipeThreshold(@NonNull RecyclerView.ViewHolder viewHolder) {
return 0.2f;
}
@Override
public void onChildDraw(@NonNull Canvas c,
@NonNull RecyclerView recyclerView,
@NonNull RecyclerView.ViewHolder viewHolder,
float dX, float dY, int actionState, boolean isCurrentlyActive) {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
double maxDistance = recyclerView.getWidth() * 0.5f;
double distance = Math.sqrt(dX * dX + dY * dY);
double fraction = distance / maxDistance;
if (fraction > 1) {
fraction = 1;
}
int itemCount = recyclerView.getChildCount();
for (int i = 0; i < itemCount; i++) {
View view = recyclerView.getChildAt(i);
int level = itemCount - i - 1;
if (level > 0) {
if (level < MyLayoutManager.showCount -1) {
view.setTranslationY((float) (40 * (level - fraction)));
view.setTranslationX((float) (40 * (level - fraction)));
}
}
}
}
}
MainActivity.java
import android.os.Bundle;
import android.view.Window;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
List<MyPicBean> mPicList = new ArrayList<>();
for (int i = 1; i <= 9; i++) {
mPicList.add(new MyPicBean(R.drawable.ic_launcher_background, "图" + i, i));
}
RecyclerView mRecyclerView = findViewById(R.id.test_rv);
MyLayoutManager mManager = new MyLayoutManager();
mRecyclerView.setLayoutManager(mManager);
MyPicAdapter mAdapter = new MyPicAdapter(this, mPicList);
mRecyclerView.setAdapter(mAdapter);
ItemTouchHelper.Callback callback = new MyItemTouchHelperCallback(
mRecyclerView, mAdapter, mPicList);
ItemTouchHelper helper = new ItemTouchHelper(callback);
helper.attachToRecyclerView(mRecyclerView);
}
}
效果
代码示例
地址:GitHub
ItemDecoration分析
ItemDecoration 可以用作设置分割线等效果; 当自定义 ItemDecoration 时,需要继承自 RecyclerView.ItemDecoration,根据需要重写方法 getItemOffsets、onDraw、onDrawOver。
getItemOffsets 方法,获取 Item 的偏移量,结果保存在第一个参数outRect中; 它仅仅获取屏幕内的 item;
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state)
onDraw 方法,进行绘制,是在 item 之前进行绘制,也就是会被 item 给挡住。
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state)
onDrawOver 方法,也是进行绘制,是在 item 之后进行绘制,也就是会把 item 给挡住。
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state)
RecyclerView的方法
RecyclerView.setLayoutManager
设置 RecyclerView 使用的 LayoutManager
LinearLayoutManager mManager = new LinearLayoutManager(this);
mManager.setOrientation(LinearLayoutManager.HORIZONTAL);
mRecyclerView.setLayoutManager(mManager);
RecyclerView.getLayoutManager()
获取 RecyclerView 之前设置的 LayoutManager,比如之前设置的 LinearLayoutManager
LinearLayoutManager layoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
RecyclerView.getAdapter()
获取设置的适配器;
if (recyclerView.getAdapter() instanceof MyFruitAdapter) {
for (int i = 0; i < recyclerView.getChildCount(); i++) {
View view = recyclerView.getChildAt(i);
int index = recyclerView.getChildAdapterPosition(view);
}
}
RecyclerView.getChildCount()
获取子 item的个数,可见的 item 数量,并不一定是所有的 item 。
RecyclerView.getChildAt()
获取第 index 个子view
if (recyclerView.getAdapter() instanceof MyFruitAdapter) {
for (int i = 0; i < recyclerView.getChildCount(); i++) {
View view = recyclerView.getChildAt(i);
int index = recyclerView.getChildAdapterPosition(view);
}
}
RecyclerView.getChildAdapterPosition()
获取 item 在 adapter 中的位置
if (recyclerView.getAdapter() instanceof MyFruitAdapter) {
for (int i = 0; i < recyclerView.getChildCount(); i++) {
View view = recyclerView.getChildAt(i);
int index = recyclerView.getChildAdapterPosition(view);
}
}
RecyclerView.findViewHolderForAdapterPosition
获取 item 对应 position 位置,所属于的 ViewHolder
int position = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition();
RecyclerView.ViewHolder viewHolder = recyclerView.findViewHolderForAdapterPosition(position);
View itemView = viewHolder.itemView;
LinearLayoutManager 的方法
LinearLayoutManager.findFirstVisibleItemPosition
返回可见区域的第一个 item 的 position
int position = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition();
参考文档
RecyclerView 之 ItemDecoration 讲解及高级特性实践
|