前言
眼下都2020年了,你不會還在使用ListView吧?
正文
因爲最近寫的一個項目裏面有關於列表的編輯相關的功能,其實也是類似與騰訊視頻的觀看歷史的列表操作,你可以先嚐試一下,寫這個主要是業務邏輯要清晰,否則你很容易就會陷進去,走死衚衕的。
效果圖如下:
源碼如下:
RecyclerViewUseDemo
迫不及待想要自己運行在AS中的小夥伴可以直接下載或者克隆,打開即可,想了解具體開發流程和詳細的業務邏輯的小夥伴,可以繼續往下看,本章很長,請在流量和時間充足的前提下觀看,如有問題,評論即可,我會盡快解決,多說無益,開搞~
開發
① 新建項目
這一步沒有什麼好說的,但是你也要注意自己的Android Studio和Gradle的版本,我的是3.5.2。點擊項目創建
② 配置build.gradle
第一步
在工程級別的build.gradle文件中的allprojects{} 閉包中添加maven庫
maven { url "https://jitpack.io" }
第二步
在項目級別的build.gradle文件中的android{}閉包中,配置JDK的版本
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
然後在dependencies{}閉包中添加第三方的依賴庫
//綁定視圖
implementation 'com.jakewharton:butterknife:10.2.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.1'
//RecyclerView
implementation 'androidx.recyclerview:recyclerview:1.1.0'
//下拉刷新
implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0-alpha-14'
//RecyclerView適配器
implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.22'
//熱門強大的圖片加載器
implementation 'com.github.bumptech.glide:glide:4.9.0'
然後右上角 Sync Now,點擊同步你的項目配置文件,同步會下載第三方的庫文件,等待完成進行下一步。
③ 修改佈局
在此之前,爲了增加點擊效果,在res → drawable 下創建rounded_corners.xml文件
代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="rectangle">
<solid android:color="#18ffc400"/>
</shape>
</item>
<item android:state_focused="true" android:state_enabled="true">
<shape android:shape="rectangle">
<solid android:color="#0f000000"/>
</shape>
</item>
</selector>
然後在res下新建一個drawable-v21的文件夾,在文件夾中創建bg_white.xml文件,代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#20000000"
android:drawable="@drawable/rounded_corners"/>
在drawable文件下再創建一個shape_blue_bg_5.xml
代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="5dp"/>
<solid android:color="#101B53"/>
</shape>
然後是修改values文件夾下的colors.xml文件,修改原來的並增加幾個顏色,
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#1F2B5D</color>
<color name="colorPrimaryDark">#1F2B5D</color>
<color name="colorAccent">#D81B60</color>
<color name="default_color">#48558C</color>
<color name="selected_color">#009FE8</color>
<color name="app_color">#1F2B5D</color>
<color name="app_bg_color">#020C49</color>
<color name="white">#FFFFFF</color>
<color name="gray">#8A96A3</color>
<color name="yellow">#F39700</color>
</resources>
再修改一下styles.xml文件
佈局中會用到下面的圖片
icon_normal.png
icon_choose_selected.png
icon_choose_default.png
修改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"
android:background="@color/app_bg_color"
android:fitsSystemWindows="true"
tools:context=".MainActivity">
<!--頭部-->
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="RecyclerView Demo"
android:textColor="@color/white"
android:textSize="18sp" />
<TextView
android:id="@+id/tv_edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginRight="8dp"
android:padding="8dp"
android:text="編輯"
android:textColor="@color/white"
android:textSize="16sp" />
</androidx.appcompat.widget.Toolbar>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/toolbar"
android:layout_above="@+id/lay_bottom">
<!--無數據時的佈局-->
<LinearLayout
android:id="@+id/rv_normal_show"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="264dp"
android:layout_height="140dp"
android:background="@mipmap/icon_normal" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_10"
android:text="空空如也"
android:textColor="@color/gray"
android:textSize="18sp" />
</LinearLayout>
<!--沒有數據時,下拉重新添加數據-->
<com.scwang.smartrefresh.layout.SmartRefreshLayout
android:id="@+id/refresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--展示數據的列表-->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="12dp"
android:visibility="gone" />
</com.scwang.smartrefresh.layout.SmartRefreshLayout>
</RelativeLayout>
<!--底部-->
<LinearLayout
android:id="@+id/lay_bottom"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:background="@color/colorPrimary"
android:orientation="horizontal"
android:visibility="gone">
<TextView
android:id="@+id/tv_check_all"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:foreground="@drawable/bg_white"
android:gravity="center"
android:text="全選"
android:textColor="@color/white"
android:textSize="@dimen/sp_14" />
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"
android:background="@color/app_bg_color" />
<TextView
android:id="@+id/tv_delete"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:foreground="@drawable/bg_white"
android:gravity="center"
android:text="刪除"
android:textColor="@color/yellow"
android:textSize="14sp" />
</LinearLayout>
</RelativeLayout>
然後是創建一個數據實體DataResponse.java
代碼如下,複製粘貼即可:
package com.llw.recyclerviewusedemo;
import java.util.List;
/**
* 數據實體
*/
public class DataResponse {
/**
* data : [{"_id":"5e959250808d6d2fe6b56eda","author":"鳶媛","category":"Girl","createdAt":"2020-05-25 08:00:00","desc":"與其安慰自己平凡可貴,\n不如拼盡全力活得漂亮。 \u200b \u200b\u200b\u200b\u200b","images":["http://gank.io/images/f4f6d68bf30147e1bdd4ddbc6ad7c2a2"],"likeCounts":0,"publishedAt":"2020-05-25 08:00:00","stars":1,"title":"第96期","type":"Girl","url":"http://gank.io/images/f4f6d68bf30147e1bdd4ddbc6ad7c2a2","views":131},{"_id":"5e95923f808d6d2fe6b56ed8","author":"鳶媛","category":"Girl","createdAt":"2020-05-24 08:00:00","desc":"這世界總有人在笨拙地愛着你,想把全部的溫柔都給你。 \u200b\u200b\u200b\u200b","images":["http://gank.io/images/dc75cbde1d98448183e2f9514b4d1320"],"likeCounts":0,"publishedAt":"2020-05-24 08:00:00","stars":1,"title":"第95期","type":"Girl","url":"http://gank.io/images/dc75cbde1d98448183e2f9514b4d1320","views":133},{"_id":"5e95922e808d6d2fe6b56ed6","author":"鳶媛","category":"Girl","createdAt":"2020-05-23 08:00:00","desc":"陪伴本來就是這世界上最了不起的安慰\u200b。","images":["http://gank.io/images/6b2efa591564475fb8bc32291fb0007c"],"likeCounts":0,"publishedAt":"2020-05-23 08:00:00","stars":1,"title":"第94期","type":"Girl","url":"http://gank.io/images/6b2efa591564475fb8bc32291fb0007c","views":135},{"_id":"5e959200ee6ba981da2af34d","author":"鳶媛","category":"Girl","createdAt":"2020-05-22 08:00:00","desc":"長不過執念,短不過善變。","images":["http://gank.io/images/d6bba8cf5b8c40f9ad229844475e9149"],"likeCounts":0,"publishedAt":"2020-05-22 08:00:00","stars":1,"title":"第93期","type":"Girl","url":"http://gank.io/images/d6bba8cf5b8c40f9ad229844475e9149","views":192},{"_id":"5e9591dcee6ba981da2af34b","author":"鳶媛","category":"Girl","createdAt":"2020-05-21 08:00:00","desc":"無論多麼艱難的現在,終會翻篇。\n朝未來大步向前吧,別喪,別止步。","images":["http://gank.io/images/9fa43020cf724c69842eec3e13f6d21c"],"likeCounts":1,"publishedAt":"2020-05-21 08:00:00","stars":1,"title":"第92期","type":"Girl","url":"http://gank.io/images/9fa43020cf724c69842eec3e13f6d21c","views":176},{"_id":"5e9591c60bd5529b54e712af","author":"鳶媛","category":"Girl","createdAt":"2020-05-20 08:00:00","desc":"希望下一次,能喜歡上一個也喜歡自己的人 \u200b\u200b\u200b\u200b。","images":["http://gank.io/images/d237f507bf1946d2b0976e581f8aab9b"],"likeCounts":0,"publishedAt":"2020-05-20 08:00:00","stars":1,"title":"第91期","type":"Girl","url":"http://gank.io/images/d237f507bf1946d2b0976e581f8aab9b","views":180},{"_id":"5e9591b6808d6d2fe6b56ed5","author":"鳶媛","category":"Girl","createdAt":"2020-05-19 08:00:00","desc":"這個世界上,\n有些人有多冷漠,\n有些人就有多溫暖,\n希望你總會遇到那些溫暖對你的人。","images":["http://gank.io/images/25d3e3db2c1248bb917c09dc4f50a46f"],"likeCounts":0,"publishedAt":"2020-05-19 08:00:00","stars":1,"title":"第90期","type":"Girl","url":"http://gank.io/images/25d3e3db2c1248bb917c09dc4f50a46f","views":255},{"_id":"5e9591a2ee6ba981da2af34a","author":"鳶媛","category":"Girl","createdAt":"2020-05-18 08:00:00","desc":"以前對你的喜歡,\n是見你,念你,陪伴你。\n現在對你的喜歡,\n是不問,不看,不叨擾。","images":["http://gank.io/images/19c99c447e0a40a6b3ff89951957cfb1"],"likeCounts":0,"publishedAt":"2020-05-18 08:00:00","stars":1,"title":"第89期","type":"Girl","url":"http://gank.io/images/19c99c447e0a40a6b3ff89951957cfb1","views":240},{"_id":"5e959197808d6d2fe6b56ed4","author":"鳶媛","category":"Girl","createdAt":"2020-05-17 08:00:00","desc":"只要結局是喜劇,過程你要我怎麼哭都行,幸福可以來的慢一些,\n只要它是真的,如果最後能在一起,晚點我真的無所謂的。","images":["http://gank.io/images/f0c192e3e335400db8a709a07a891b2e"],"likeCounts":0,"publishedAt":"2020-05-17 08:00:00","stars":1,"title":"第88期","type":"Girl","url":"http://gank.io/images/f0c192e3e335400db8a709a07a891b2e","views":275},{"_id":"5e95915f808d6d2fe6b56ed3","author":"鳶媛","category":"Girl","createdAt":"2020-05-16 08:00:00","desc":"若不是情深似海,思念又怎會氾濫成災。","images":["http://gank.io/images/bdb35e4b3c0045c799cc7a494a3db3e0"],"likeCounts":0,"publishedAt":"2020-05-16 08:00:00","stars":1,"title":"第87期","type":"Girl","url":"http://gank.io/images/bdb35e4b3c0045c799cc7a494a3db3e0","views":437}]
* page : 1
* page_count : 10
* status : 100
* total_counts : 96
*/
private int page;
private int page_count;
private int status;
private int total_counts;
private List<DataBean> data;
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public int getPage_count() {
return page_count;
}
public void setPage_count(int page_count) {
this.page_count = page_count;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public int getTotal_counts() {
return total_counts;
}
public void setTotal_counts(int total_counts) {
this.total_counts = total_counts;
}
public List<DataBean> getData() {
return data;
}
public void setData(List<DataBean> data) {
this.data = data;
}
public static class DataBean {
/**
* _id : 5e959250808d6d2fe6b56eda
* author : 鳶媛
* category : Girl
* createdAt : 2020-05-25 08:00:00
* desc : 與其安慰自己平凡可貴,
不如拼盡全力活得漂亮。
* images : ["http://gank.io/images/f4f6d68bf30147e1bdd4ddbc6ad7c2a2"]
* likeCounts : 0
* publishedAt : 2020-05-25 08:00:00
* stars : 1
* title : 第96期
* type : Girl
* url : http://gank.io/images/f4f6d68bf30147e1bdd4ddbc6ad7c2a2
* views : 131
*/
private String _id;
private String author;
private String category;
private String createdAt;
private String desc;
private int likeCounts;
private String publishedAt;
private int stars;
private String title;
private String type;
private String url;
private int views;
private List<String> images;
private boolean select = false;
public String get_id() {
return _id;
}
public void set_id(String _id) {
this._id = _id;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getCreatedAt() {
return createdAt;
}
public void setCreatedAt(String createdAt) {
this.createdAt = createdAt;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public int getLikeCounts() {
return likeCounts;
}
public void setLikeCounts(int likeCounts) {
this.likeCounts = likeCounts;
}
public String getPublishedAt() {
return publishedAt;
}
public void setPublishedAt(String publishedAt) {
this.publishedAt = publishedAt;
}
public int getStars() {
return stars;
}
public void setStars(int stars) {
this.stars = stars;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getViews() {
return views;
}
public void setViews(int views) {
this.views = views;
}
public List<String> getImages() {
return images;
}
public void setImages(List<String> images) {
this.images = images;
}
public boolean isSelect() {
return select;
}
public void setSelect(boolean select) {
this.select = select;
}
}
}
再創建一個JsonData.java,存放用於轉換的JSON數據
代碼如下,複製粘貼即可:
package com.llw.recyclerviewusedemo;
public class JsonData {
public static String JSON = "{\"data\":[{\"_id\":\"5e959250808d6d2fe6b56eda\",\"author\":\"\\u9e22\\u5a9b\",\"category\":\"Girl\",\"createdAt\":\"2020-05-25 08:00:00\",\"desc\":\"\\u4e0e\\u5176\\u5b89\\u6170\\u81ea\\u5df1\\u5e73\\u51e1\\u53ef\\u8d35\\uff0c\\n\\u4e0d\\u5982\\u62fc\\u5c3d\\u5168\\u529b\\u6d3b\\u5f97\\u6f02\\u4eae\\u3002 \\u200b \\u200b\\u200b\\u200b\\u200b\",\"images\":[\"http://gank.io/images/f4f6d68bf30147e1bdd4ddbc6ad7c2a2\"],\"likeCounts\":0,\"publishedAt\":\"2020-05-25 08:00:00\",\"stars\":1,\"title\":\"\\u7b2c96\\u671f\",\"type\":\"Girl\",\"url\":\"http://gank.io/images/f4f6d68bf30147e1bdd4ddbc6ad7c2a2\",\"views\":131},{\"_id\":\"5e95923f808d6d2fe6b56ed8\",\"author\":\"\\u9e22\\u5a9b\",\"category\":\"Girl\",\"createdAt\":\"2020-05-24 08:00:00\",\"desc\":\"\\u8fd9\\u4e16\\u754c\\u603b\\u6709\\u4eba\\u5728\\u7b28\\u62d9\\u5730\\u7231\\u7740\\u4f60\\uff0c\\u60f3\\u628a\\u5168\\u90e8\\u7684\\u6e29\\u67d4\\u90fd\\u7ed9\\u4f60\\u3002 \\u200b\\u200b\\u200b\\u200b\",\"images\":[\"http://gank.io/images/dc75cbde1d98448183e2f9514b4d1320\"],\"likeCounts\":0,\"publishedAt\":\"2020-05-24 08:00:00\",\"stars\":1,\"title\":\"\\u7b2c95\\u671f\",\"type\":\"Girl\",\"url\":\"http://gank.io/images/dc75cbde1d98448183e2f9514b4d1320\",\"views\":133},{\"_id\":\"5e95922e808d6d2fe6b56ed6\",\"author\":\"\\u9e22\\u5a9b\",\"category\":\"Girl\",\"createdAt\":\"2020-05-23 08:00:00\",\"desc\":\"\\u966a\\u4f34\\u672c\\u6765\\u5c31\\u662f\\u8fd9\\u4e16\\u754c\\u4e0a\\u6700\\u4e86\\u4e0d\\u8d77\\u7684\\u5b89\\u6170\\u200b\\u3002\",\"images\":[\"http://gank.io/images/6b2efa591564475fb8bc32291fb0007c\"],\"likeCounts\":0,\"publishedAt\":\"2020-05-23 08:00:00\",\"stars\":1,\"title\":\"\\u7b2c94\\u671f\",\"type\":\"Girl\",\"url\":\"http://gank.io/images/6b2efa591564475fb8bc32291fb0007c\",\"views\":135},{\"_id\":\"5e959200ee6ba981da2af34d\",\"author\":\"\\u9e22\\u5a9b\",\"category\":\"Girl\",\"createdAt\":\"2020-05-22 08:00:00\",\"desc\":\"\\u957f\\u4e0d\\u8fc7\\u6267\\u5ff5\\uff0c\\u77ed\\u4e0d\\u8fc7\\u5584\\u53d8\\u3002\",\"images\":[\"http://gank.io/images/d6bba8cf5b8c40f9ad229844475e9149\"],\"likeCounts\":0,\"publishedAt\":\"2020-05-22 08:00:00\",\"stars\":1,\"title\":\"\\u7b2c93\\u671f\",\"type\":\"Girl\",\"url\":\"http://gank.io/images/d6bba8cf5b8c40f9ad229844475e9149\",\"views\":192},{\"_id\":\"5e9591dcee6ba981da2af34b\",\"author\":\"\\u9e22\\u5a9b\",\"category\":\"Girl\",\"createdAt\":\"2020-05-21 08:00:00\",\"desc\":\"\\u65e0\\u8bba\\u591a\\u4e48\\u8270\\u96be\\u7684\\u73b0\\u5728\\uff0c\\u7ec8\\u4f1a\\u7ffb\\u7bc7\\u3002\\n\\u671d\\u672a\\u6765\\u5927\\u6b65\\u5411\\u524d\\u5427\\uff0c\\u522b\\u4e27\\uff0c\\u522b\\u6b62\\u6b65\\u3002\",\"images\":[\"http://gank.io/images/9fa43020cf724c69842eec3e13f6d21c\"],\"likeCounts\":1,\"publishedAt\":\"2020-05-21 08:00:00\",\"stars\":1,\"title\":\"\\u7b2c92\\u671f\",\"type\":\"Girl\",\"url\":\"http://gank.io/images/9fa43020cf724c69842eec3e13f6d21c\",\"views\":176},{\"_id\":\"5e9591c60bd5529b54e712af\",\"author\":\"\\u9e22\\u5a9b\",\"category\":\"Girl\",\"createdAt\":\"2020-05-20 08:00:00\",\"desc\":\"\\u5e0c\\u671b\\u4e0b\\u4e00\\u6b21\\uff0c\\u80fd\\u559c\\u6b22\\u4e0a\\u4e00\\u4e2a\\u4e5f\\u559c\\u6b22\\u81ea\\u5df1\\u7684\\u4eba \\u200b\\u200b\\u200b\\u200b\\u3002\",\"images\":[\"http://gank.io/images/d237f507bf1946d2b0976e581f8aab9b\"],\"likeCounts\":0,\"publishedAt\":\"2020-05-20 08:00:00\",\"stars\":1,\"title\":\"\\u7b2c91\\u671f\",\"type\":\"Girl\",\"url\":\"http://gank.io/images/d237f507bf1946d2b0976e581f8aab9b\",\"views\":180},{\"_id\":\"5e9591b6808d6d2fe6b56ed5\",\"author\":\"\\u9e22\\u5a9b\",\"category\":\"Girl\",\"createdAt\":\"2020-05-19 08:00:00\",\"desc\":\"\\u8fd9\\u4e2a\\u4e16\\u754c\\u4e0a\\uff0c\\n\\u6709\\u4e9b\\u4eba\\u6709\\u591a\\u51b7\\u6f20\\uff0c\\n\\u6709\\u4e9b\\u4eba\\u5c31\\u6709\\u591a\\u6e29\\u6696\\uff0c\\n\\u5e0c\\u671b\\u4f60\\u603b\\u4f1a\\u9047\\u5230\\u90a3\\u4e9b\\u6e29\\u6696\\u5bf9\\u4f60\\u7684\\u4eba\\u3002\",\"images\":[\"http://gank.io/images/25d3e3db2c1248bb917c09dc4f50a46f\"],\"likeCounts\":0,\"publishedAt\":\"2020-05-19 08:00:00\",\"stars\":1,\"title\":\"\\u7b2c90\\u671f\",\"type\":\"Girl\",\"url\":\"http://gank.io/images/25d3e3db2c1248bb917c09dc4f50a46f\",\"views\":255},{\"_id\":\"5e9591a2ee6ba981da2af34a\",\"author\":\"\\u9e22\\u5a9b\",\"category\":\"Girl\",\"createdAt\":\"2020-05-18 08:00:00\",\"desc\":\"\\u4ee5\\u524d\\u5bf9\\u4f60\\u7684\\u559c\\u6b22\\uff0c\\n\\u662f\\u89c1\\u4f60\\uff0c\\u5ff5\\u4f60\\uff0c\\u966a\\u4f34\\u4f60\\u3002\\n\\u73b0\\u5728\\u5bf9\\u4f60\\u7684\\u559c\\u6b22\\uff0c\\n\\u662f\\u4e0d\\u95ee\\uff0c\\u4e0d\\u770b\\uff0c\\u4e0d\\u53e8\\u6270\\u3002\",\"images\":[\"http://gank.io/images/19c99c447e0a40a6b3ff89951957cfb1\"],\"likeCounts\":0,\"publishedAt\":\"2020-05-18 08:00:00\",\"stars\":1,\"title\":\"\\u7b2c89\\u671f\",\"type\":\"Girl\",\"url\":\"http://gank.io/images/19c99c447e0a40a6b3ff89951957cfb1\",\"views\":240},{\"_id\":\"5e959197808d6d2fe6b56ed4\",\"author\":\"\\u9e22\\u5a9b\",\"category\":\"Girl\",\"createdAt\":\"2020-05-17 08:00:00\",\"desc\":\"\\u53ea\\u8981\\u7ed3\\u5c40\\u662f\\u559c\\u5267\\uff0c\\u8fc7\\u7a0b\\u4f60\\u8981\\u6211\\u600e\\u4e48\\u54ed\\u90fd\\u884c\\uff0c\\u5e78\\u798f\\u53ef\\u4ee5\\u6765\\u7684\\u6162\\u4e00\\u4e9b\\uff0c\\n\\u53ea\\u8981\\u5b83\\u662f\\u771f\\u7684\\uff0c\\u5982\\u679c\\u6700\\u540e\\u80fd\\u5728\\u4e00\\u8d77\\uff0c\\u665a\\u70b9\\u6211\\u771f\\u7684\\u65e0\\u6240\\u8c13\\u7684\\u3002\",\"images\":[\"http://gank.io/images/f0c192e3e335400db8a709a07a891b2e\"],\"likeCounts\":0,\"publishedAt\":\"2020-05-17 08:00:00\",\"stars\":1,\"title\":\"\\u7b2c88\\u671f\",\"type\":\"Girl\",\"url\":\"http://gank.io/images/f0c192e3e335400db8a709a07a891b2e\",\"views\":275},{\"_id\":\"5e95915f808d6d2fe6b56ed3\",\"author\":\"\\u9e22\\u5a9b\",\"category\":\"Girl\",\"createdAt\":\"2020-05-16 08:00:00\",\"desc\":\"\\u82e5\\u4e0d\\u662f\\u60c5\\u6df1\\u4f3c\\u6d77\\uff0c\\u601d\\u5ff5\\u53c8\\u600e\\u4f1a\\u6cdb\\u6ee5\\u6210\\u707e\\u3002\",\"images\":[\"http://gank.io/images/bdb35e4b3c0045c799cc7a494a3db3e0\"],\"likeCounts\":0,\"publishedAt\":\"2020-05-16 08:00:00\",\"stars\":1,\"title\":\"\\u7b2c87\\u671f\",\"type\":\"Girl\",\"url\":\"http://gank.io/images/bdb35e4b3c0045c799cc7a494a3db3e0\",\"views\":437}],\"page\":1,\"page_count\":10,\"status\":100,\"total_counts\":96}";
}
④ 創建列表的item佈局文件
在layout文件下創建item_data_list.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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:orientation="vertical">
<LinearLayout
android:id="@+id/item_data"
android:foreground="@drawable/bg_white"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/shape_blue_bg_5"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="12dp">
<ImageView
android:id="@+id/iv_check"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginRight="12dp"
android:background="@mipmap/icon_choose_default"
android:button="@null" />
<ImageView
android:id="@+id/iv_img"
android:layout_width="150dp"
android:layout_height="200dp"
android:background="@drawable/ic_launcher_background"
android:scaleType="centerCrop" />
<TextView
android:id="@+id/tv_video_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="12dp"
android:text="測試數據"
android:textColor="@color/white"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>
⑤ 列表適配器
創建一個適配器DataAdapter.java
代碼如下:
package com.llw.recyclerviewusedemo;
import android.view.View;
import android.widget.ImageView;
import androidx.annotation.Nullable;
import com.bumptech.glide.Glide;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import java.util.List;
/**
* 適配器
*/
public class DataAdapter extends BaseQuickAdapter<DataResponse.DataBean, BaseViewHolder> {
private static final int STATE_DEFAULT = 0;//默認狀態
int mEditMode = STATE_DEFAULT;
public DataAdapter(int layoutResId, @Nullable List<DataResponse.DataBean> data) {
super(layoutResId, data);
}
@Override
protected void convert(BaseViewHolder helper, DataResponse.DataBean item) {
//Glide加載網絡圖片
Glide.with(mContext).load(item.getUrl()).into((ImageView) helper.getView(R.id.iv_img));
//TextView賦值
helper.setText(R.id.tv_video_info, item.getAuthor());
helper.addOnClickListener(R.id.item_data);//添加item點擊事件
if (mEditMode == STATE_DEFAULT) {
//默認不顯示
helper.getView(R.id.iv_check).setVisibility(View.GONE);
} else {
//顯示 顯示之後再做點擊之後的判斷
helper.getView(R.id.iv_check).setVisibility(View.VISIBLE);
if (item.isSelect()) {//點擊時,true 選中
helper.getView(R.id.iv_check).setBackgroundResource(R.mipmap.icon_choose_selected);
} else {//false 取消選中
helper.getView(R.id.iv_check).setBackgroundResource(R.mipmap.icon_choose_default);
}
}
}
/**
* 設置編輯狀態 接收Activity中傳遞的值,並改變Adapter的狀態
*/
public void setEditMode(int editMode) {
mEditMode = editMode;
notifyDataSetChanged();//刷新
}
}
⑥ 主要邏輯編寫
進入到MainActivity.java
這裏綁定一些控件並聲明一些需要用到的變量
初始化列表數據
//初始化列表數據
private void initList() {
mAdapter = new DataAdapter(R.layout.item_data_list, mList);//綁定視圖和數據
rv.setLayoutManager(new LinearLayoutManager(this));//設置線性佈局管理器
rv.setAdapter(mAdapter);//設置適配器
Gson gson = new Gson();
DataResponse dataBean = gson.fromJson(JsonData.JSON, DataResponse.class);//解析數據
List<DataResponse.DataBean> resultsBeans = dataBean.getData();
if (resultsBeans.size() > 0) {
mList.clear();
mList.addAll(resultsBeans);
mAdapter.notifyDataSetChanged();//刷新數據
rv.setVisibility(View.VISIBLE);
rvNormalShow.setVisibility(View.GONE);
} else {
rv.setVisibility(View.GONE);
rvNormalShow.setVisibility(View.VISIBLE);
}
refresh.finishRefresh();//數據加載出來之後,結束下拉動作
}
處理點擊事件
//頁面的點擊事件
@OnClick({R.id.tv_edit, R.id.tv_check_all, R.id.tv_delete})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.tv_edit://編輯
updateEditState();
break;
case R.id.tv_check_all://全選
setAllItemChecked();
break;
case R.id.tv_delete://刪除
deleteCheckItem();
break;
}
}
改變編輯狀態
//改變編輯狀態
private void updateEditState() {
mEditMode = mEditMode == STATE_DEFAULT ? STATE_EDIT : STATE_DEFAULT;
if (mEditMode == STATE_EDIT) {
tvEdit.setText("取消");
layBottom.setVisibility(View.VISIBLE);
editorStatus = true;//處於編輯狀態
} else {
tvEdit.setText("編輯");
layBottom.setVisibility(View.GONE);
editorStatus = false;//處於默認狀態
setAllItemUnchecked();//取消全選
}
mAdapter.setEditMode(mEditMode);//刷新Adapter
mAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
@Override
public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
if (editorStatus) {//編輯狀態
DataResponse.DataBean dataBean = mList.get(position);//賦值
boolean isSelect = dataBean.isSelect();
if (!isSelect) {
index++;
dataBean.setSelect(true);
} else {
dataBean.setSelect(false);
index--;
}
if (index == 0) {//當前選中item數量
tvDelete.setText("刪除");
} else {
tvDelete.setText("刪除(" + index + ")");
}
mAdapter.notifyDataSetChanged();
}
}
});
}
全部選中
//全部選中
private void setAllItemChecked() {
if (mAdapter == null) return;
for (int i = 0; i < mList.size(); i++) {
mList.get(i).setSelect(true);
}
mAdapter.notifyDataSetChanged();
index = mList.size();
tvDelete.setText("刪除(" + index + ")");
}
取消全部選中
//取消全部選中
private void setAllItemUnchecked() {
if (mAdapter == null) return;
for (int i = 0; i < mList.size(); i++) {
mList.get(i).setSelect(false);
}
mAdapter.notifyDataSetChanged();
tvDelete.setText("刪除");
index = 0;
}
刪除選中的item
//刪除選中的item
private void deleteCheckItem() {
if (mAdapter == null) return;
for (int i = mList.size() - 1; i >= 0; i--) {
if (mList.get(i).isSelect() == true) {
mList.remove(i);
}
}
//刪除選中的item之後判斷是否還有數據,沒有則退出編輯模式
if (mList.size() != 0) {
index = 0;//刪除之後置爲0
tvDelete.setText("刪除");
}else {
tvEdit.setText("編輯");
layBottom.setVisibility(View.GONE);
editorStatus = false;
//沒有數據自然也不存在編輯了
tvEdit.setVisibility(View.GONE);
rvNormalShow.setVisibility(View.VISIBLE);
//啓用下拉
refresh.setEnableRefresh(true);
//下拉刷新
refresh.setOnRefreshListener(refreshLayout -> {
//重新裝填數據
initList();
mEditMode = STATE_DEFAULT;//恢復默認狀態
editorStatus = false;//恢復默認狀態
tvEdit.setVisibility(View.VISIBLE);//顯示編輯
});
}
mAdapter.notifyDataSetChanged();//刷新
}
最後在onCreate()方法中使用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
initList();
//禁用下拉和上拉
refresh.setEnableRefresh(false);
refresh.setEnableLoadMore(false);
}
做完這些基本上功能就已經都實現了,下面就是錦上添花了,增加動畫效果,
⑦ 增加動畫效果
列表的出現動畫,在res下創建一個anim文件夾,這下面有兩個xml文件
layout_animation_from_bottom.xml
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation
xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="@anim/item_animation_from_bottom"
android:delay="15%"
android:animationOrder="normal"
/>
item_animation_from_bottom.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500">
<translate
android:fromYDelta="50%p"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:toYDelta="0" />
<alpha
android:fromAlpha="0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:toAlpha="1" />
</set>
然後創建一個動畫類RecyclerViewAnimation.java,用來使用
代碼如下:
package com.llw.recyclerviewusedemo;
import android.content.Context;
import android.view.animation.AnimationUtils;
import android.view.animation.LayoutAnimationController;
import androidx.recyclerview.widget.RecyclerView;
/**
* RecyclerView動畫
*/
public class RecyclerViewAnimation {
//數據變化時顯示動畫
public static void runLayoutAnimation(final RecyclerView recyclerView) {
final Context context = recyclerView.getContext();
final LayoutAnimationController controller =
AnimationUtils.loadLayoutAnimation(context, R.anim.layout_animation_from_bottom);
recyclerView.setLayoutAnimation(controller);
recyclerView.getAdapter().notifyDataSetChanged();
recyclerView.scheduleLayoutAnimation();
}
}
使用方法
import static com.llw.recyclerviewusedemo.RecyclerViewAnimation.runLayoutAnimation;//導入
MainActivity.java完整代碼
package com.llw.recyclerviewusedemo;
import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.google.gson.Gson;
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import static com.llw.recyclerviewusedemo.RecyclerViewAnimation.runLayoutAnimation;
public class MainActivity extends AppCompatActivity {
@BindView(R.id.tv_edit)
TextView tvEdit;//編輯
@BindView(R.id.rv_normal_show)
LinearLayout rvNormalShow;//沒有數據時展示的佈局
@BindView(R.id.rv)
RecyclerView rv;//列表
@BindView(R.id.refresh)
SmartRefreshLayout refresh;//刷新佈局
@BindView(R.id.tv_check_all)
TextView tvCheckAll;//全選
@BindView(R.id.tv_delete)
TextView tvDelete;//刪除
@BindView(R.id.lay_bottom)
LinearLayout layBottom;//底部佈局
private static final int STATE_DEFAULT = 0;//默認狀態
private static final int STATE_EDIT = 1;//編輯狀態
private int mEditMode = STATE_DEFAULT;
private boolean editorStatus = false;//是否爲編輯狀態
private int index = 0;//當前選中的item數
List<DataResponse.DataBean> mList = new ArrayList<>();//列表
DataAdapter mAdapter;//適配器
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
initList();
//禁用下拉和上拉
refresh.setEnableRefresh(false);
refresh.setEnableLoadMore(false);
}
//初始化列表數據
private void initList() {
mAdapter = new DataAdapter(R.layout.item_data_list, mList);//綁定視圖和數據
rv.setLayoutManager(new LinearLayoutManager(this));//設置線性佈局管理器
rv.setAdapter(mAdapter);//設置適配器
Gson gson = new Gson();
DataResponse dataBean = gson.fromJson(JsonData.JSON, DataResponse.class);//解析數據
List<DataResponse.DataBean> resultsBeans = dataBean.getData();
if (resultsBeans.size() > 0) {
mList.clear();
mList.addAll(resultsBeans);
mAdapter.notifyDataSetChanged();//刷新數據
runLayoutAnimation(rv);//動畫顯示
rv.setVisibility(View.VISIBLE);
rvNormalShow.setVisibility(View.GONE);
} else {
rv.setVisibility(View.GONE);
rvNormalShow.setVisibility(View.VISIBLE);
}
refresh.finishRefresh();//數據加載出來之後,結束下拉動作
}
//頁面的點擊事件
@OnClick({R.id.tv_edit, R.id.tv_check_all, R.id.tv_delete})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.tv_edit://編輯
updateEditState();
break;
case R.id.tv_check_all://全選
setAllItemChecked();
break;
case R.id.tv_delete://刪除
deleteCheckItem();
break;
}
}
//改變編輯狀態
private void updateEditState() {
mEditMode = mEditMode == STATE_DEFAULT ? STATE_EDIT : STATE_DEFAULT;
if (mEditMode == STATE_EDIT) {
tvEdit.setText("取消");
layBottom.setVisibility(View.VISIBLE);
editorStatus = true;
} else {
tvEdit.setText("編輯");
layBottom.setVisibility(View.GONE);
editorStatus = false;
setAllItemUnchecked();//取消全選
}
mAdapter.setEditMode(mEditMode);
mAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
@Override
public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
if (editorStatus) {//編輯狀態
DataResponse.DataBean dataBean = mList.get(position);
boolean isSelect = dataBean.isSelect();
if (!isSelect) {
index++;
dataBean.setSelect(true);
} else {
dataBean.setSelect(false);
index--;
}
if (index == 0) {
tvDelete.setText("刪除");
} else {
tvDelete.setText("刪除(" + index + ")");
}
mAdapter.notifyDataSetChanged();
}
}
});
}
//全部選中
private void setAllItemChecked() {
if (mAdapter == null) return;
for (int i = 0; i < mList.size(); i++) {
mList.get(i).setSelect(true);
}
mAdapter.notifyDataSetChanged();
index = mList.size();
tvDelete.setText("刪除(" + index + ")");
}
//取消全部選中
private void setAllItemUnchecked() {
if (mAdapter == null) return;
for (int i = 0; i < mList.size(); i++) {
mList.get(i).setSelect(false);
}
mAdapter.notifyDataSetChanged();
tvDelete.setText("刪除");
index = 0;
}
//刪除選中的item
private void deleteCheckItem() {
if (mAdapter == null) return;
for (int i = mList.size() - 1; i >= 0; i--) {
if (mList.get(i).isSelect() == true) {
mList.remove(i);
}
}
//刪除選中的item之後判斷是否還有數據,沒有則退出編輯模式
if (mList.size() != 0) {
index = 0;//刪除之後置爲0
tvDelete.setText("刪除");
}else {
tvEdit.setText("編輯");
layBottom.setVisibility(View.GONE);
editorStatus = false;
//沒有數據自然也不存在編輯了
tvEdit.setVisibility(View.GONE);
rvNormalShow.setVisibility(View.VISIBLE);
//啓用下拉
refresh.setEnableRefresh(true);
//下拉刷新
refresh.setOnRefreshListener(refreshLayout -> {
//重新裝填數據
initList();
index = 0;
mEditMode = STATE_DEFAULT;//恢復默認狀態
editorStatus = false;//恢復默認狀態
tvDelete.setText("刪除");
tvEdit.setVisibility(View.VISIBLE);//顯示編輯
});
}
mAdapter.notifyDataSetChanged();
runLayoutAnimation(rv);//動畫顯示
}
}
尾聲
感謝每一個閱讀的人,寫文章只爲積累自己的經驗,不至於忘記,如果能對看文章的您有幫助,那就更好了,我是初學者-Study,山高水長,後會有期~