Android中RecyclerView配合BaseRecyclerViewAdapterHelper實(shí)現(xiàn)展開收縮功能(三)

前面一篇介紹了RecyclerView的下拉刷新和上拉加載垦巴,今天介紹非樹狀列表的展開和隱藏功能。數(shù)據(jù)是在同一級列表返回矿咕。

項(xiàng)目說明:

一,使用的AndroidStudio版本為3.2.1丐怯,gradle-4.6

二,使用的RecyclerView的adapter是BaseRecyclerViewAdapterHelper,github上對應(yīng)的地址如下

github地址為:https://github.com/CymChad/BaseRecyclerViewAdapterHelper
對應(yīng)的簡書說明地址為:http://www.reibang.com/p/b343fcff51b0

展示效果:

jsrecyclerview2.gif

為什么寫這篇簡書的說明和坑點(diǎn):

一,這其實(shí)是一個(gè)很小的功能點(diǎn)庶诡,但是這其中還是有很多坑,所以寫這篇簡書來記錄和分享給其他需要的人咆课。

二,列表數(shù)據(jù)超過10條的時(shí)候,點(diǎn)擊第一條的數(shù)據(jù)扯俱,會(huì)造成第11條數(shù)據(jù)也會(huì)有相應(yīng)的改變书蚪。

三,列表加載了數(shù)據(jù),在向上滑動(dòng)的過程中迅栅,明明是展開的狀態(tài)殊校,但是他會(huì)因?yàn)榱斜淼闹赜脤?dǎo)致數(shù)據(jù)錯(cuò)亂,會(huì)重新顯示隱藏狀態(tài)读存。

現(xiàn)在正式開始

1为流,基本配置如依賴包呕屎,下拉刷新功能等在RecyclerView系列(二)中已經(jīng)說明,不做描述敬察,重點(diǎn)說坑點(diǎn)以及實(shí)現(xiàn)方法秀睛。

2,一般在實(shí)現(xiàn)每一個(gè)item的點(diǎn)擊事件的時(shí)候使用的方法如下:在對應(yīng)的activity中使用對應(yīng)的adapter實(shí)現(xiàn)點(diǎn)擊事件(如下)莲祸,這樣做的弊端是拿不到每一個(gè)你所點(diǎn)擊的item所對應(yīng)的控件蹂安,而且傳參中View view對應(yīng)的view也無法拿到外部view對應(yīng)的id,從而無法控制外部view的顯示和隱藏锐帜。

        //6.1田盈,給recyclerView的每一個(gè)子列表添加點(diǎn)擊事件
//        mTestAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
////            @Override
////            public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
////                Toast.makeText(MainActivity.this, "我點(diǎn)擊了第" + position + "個(gè)子view",
////                        Toast.LENGTH_SHORT).show();
////            }
////        });

3,正確做法是如下中6.2所示缴阎,使用對應(yīng)的recyclerview實(shí)現(xiàn)點(diǎn)擊事件允瞧,點(diǎn)擊事件中更新實(shí)例中自定義的isShow參數(shù)的狀態(tài),這個(gè)isShow是對應(yīng)到每個(gè)item的蛮拔,所以不會(huì)串瓷式。然后 mTestAdapter.notifyDataSetChanged();更新數(shù)據(jù)。對應(yīng)的適配器中就會(huì)刷新數(shù)據(jù)语泽。

package com.mumu.jsrecyclerview2;

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.listener.OnItemChildClickListener;
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
import com.scwang.smartrefresh.layout.api.RefreshLayout;
import com.scwang.smartrefresh.layout.listener.OnRefreshLoadMoreListener;

import java.util.ArrayList;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;

public class MainActivity extends AppCompatActivity {

    @BindView(R.id.rv_test)
    RecyclerView rvTest;
    @BindView(R.id.srl_test)
    SmartRefreshLayout srlTest;
    private TestAdapter mTestAdapter;
    private ArrayList<TestEntity.ResultBean.ListBean> mTestList;
    private Unbinder unbinder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        unbinder = ButterKnife.bind(this);

        initView();
    }

    private void initView() {

        //初始化的時(shí)候默認(rèn)沒有數(shù)據(jù)贸典,顯示空的布局
        getData(1);
        refreshView();
        smartRefreshView();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbinder.unbind();
    }

    /**
     * 刷新消息列表
     */
    private void refreshView() {
        //1,加載空布局文件,便于第五步適配器在沒有數(shù)據(jù)的時(shí)候加載
        View emptyView = View.inflate(this, R.layout.empty_view, null);
        //2踱卵,設(shè)置LayoutManager,LinearLayoutManager表示豎直向下
        rvTest.setLayoutManager(new LinearLayoutManager(this));
        //3廊驼,初始化一個(gè)無數(shù)據(jù)的適配器
        mTestAdapter = new TestAdapter();
        //4,綁定recyclerView和適配器
        rvTest.setAdapter(mTestAdapter);
        //5惋砂,給recyclerView設(shè)置空布局
        mTestAdapter.setEmptyView(emptyView);
        //6.1妒挎,給recyclerView的每一個(gè)子列表添加點(diǎn)擊事件
//        mTestAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
////            @Override
////            public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
////                Toast.makeText(MainActivity.this, "我點(diǎn)擊了第" + position + "個(gè)子view",
////                        Toast.LENGTH_SHORT).show();
////            }
////        });
        //6.2,給recyclerView的每一個(gè)子列表添加點(diǎn)擊事件
        // TODO: 2019/1/10 這不能使用上面6.1的點(diǎn)擊事件的方法西饵,使用以上方法會(huì)導(dǎo)致點(diǎn)擊混亂酝掩,滑動(dòng)導(dǎo)致已經(jīng)展開的item隱藏
        rvTest.addOnItemTouchListener(new OnItemChildClickListener() {
            @Override
            public void onSimpleItemChildClick(BaseQuickAdapter adapter, View view, int position) {
                switch (view.getId()) {
                    case R.id.rl_item_title:
                        // TODO: 2019/1/11 1,點(diǎn)擊按鈕的時(shí)候更新在實(shí)例中對應(yīng)的isShow數(shù)據(jù)
                        if (mTestList.get(position).isShow()) {
                            mTestList.get(position).setShow(false);
                            Toast.makeText(MainActivity.this,"第"+position+"個(gè)隱藏",Toast.LENGTH_SHORT).show();
                        } else {
                            mTestList.get(position).setShow(true);
                            Toast.makeText(MainActivity.this,"第"+position+"個(gè)展開",Toast.LENGTH_SHORT).show();
                        }
                        // TODO: 2019/1/11,2眷柔,適配器更新數(shù)據(jù)期虾,刷新列表,更新狀態(tài)
                        mTestAdapter.notifyDataSetChanged();

                        break;
                    default:
                        break;
                }
            }
        });
    }

    /**
     * MainActivity中增加下拉刷新和上拉加載的監(jiān)聽方法
     */
    private void smartRefreshView() {
        srlTest.setOnRefreshLoadMoreListener(new OnRefreshLoadMoreListener() {
            @Override
            public void onRefresh(@NonNull RefreshLayout refreshLayout) {
                //下拉刷新,一般添加調(diào)用接口獲取數(shù)據(jù)的方法
                getData(2);
                refreshLayout.finishRefresh();
            }

            @Override
            public void onLoadMore(@NonNull RefreshLayout refreshLayout) {
                //上拉加載驯嘱,一般添加調(diào)用接口獲取更多數(shù)據(jù)的方法
                getData(3);
                refreshLayout.finishLoadMoreWithNoMoreData();
            }
        });
    }

    /**
     * 獲取數(shù)據(jù)的方法
     * 該方法純屬展示各種效果镶苞,實(shí)際應(yīng)用時(shí)候請自己根據(jù)需求做判斷即可
     *
     * @param mode 模式:1為剛開始進(jìn)來加載數(shù)據(jù) 空數(shù)據(jù) 2為下拉刷新 3為上拉加載
     */
    private void getData(int mode) {
        //添加臨時(shí)數(shù)據(jù),一般直接從接口獲取
        switch (mode) {
            case 1:

                break;
            case 2:
                mTestList = new ArrayList<>();
                for (int i = 0; i < 15; i++) {
                    mTestList.add(new TestEntity.ResultBean.ListBean("我有一個(gè)小狗", "我有一個(gè)小狗我有一個(gè)小狗我有一個(gè)小狗我有一個(gè)小狗我有一個(gè)小狗"));
                }
                //更新數(shù)據(jù)
                mTestAdapter.setNewData(mTestList);
                break;
            case 3:
                for (int i = 0; i < 15; i++) {
                    mTestList.add(new TestEntity.ResultBean.ListBean("我有一個(gè)小狗", "我有一個(gè)小狗我有一個(gè)小狗我有一個(gè)小狗我有一個(gè)小狗我有一個(gè)小狗"));
                }
                mTestAdapter.setNewData(mTestList);
                break;
            default:
                mTestList = new ArrayList<>();
                for (int i = 0; i < 10; i++) {
                    mTestList.add(new TestEntity.ResultBean.ListBean("我有一個(gè)小狗", "我有一個(gè)小狗我有一個(gè)小狗我有一個(gè)小狗我有一個(gè)小狗我有一個(gè)小狗"));
                }
                break;
        }
    }
}

4鞠评,對應(yīng)是實(shí)例中只增加了一個(gè)isShow參數(shù)來記錄狀態(tài)

package com.mumu.jsrecyclerview2;

import java.io.Serializable;
import java.util.List;

public class TestEntity implements Serializable {

    /**
     * Success : true
     * StatusCode : 200
     * Result : {"list":[{"TestTitle":"我愛小狗","TestNessage":"我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗"},{"TestTitle":"我愛小狗","TestNessage":"我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗"},{"TestTitle":"我愛小狗","TestNessage":"我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗"},{"TestTitle":"我愛小狗","TestNessage":"我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗"},{"TestTitle":"我愛小狗","TestNessage":"我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗"}]}
     */

    private ResultBean Result;

    public ResultBean getResult() {
        return Result;
    }

    public void setResult(ResultBean Result) {
        this.Result = Result;
    }

    public static class ResultBean {
        private List<ListBean> list;

        public List<ListBean> getList() {
            return list;
        }

        public void setList(List<ListBean> list) {
            this.list = list;
        }

        public static class ListBean {
            /**
             * TestTitle : 我愛小狗
             * TestMessage : 我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗我愛小狗
             * isShow: 是否顯示詳細(xì)消息茂蚓,后臺(tái)沒有返回,屬于自己添加賦值,用來記錄每一個(gè)item的顯示詳情狀態(tài)
             */

            private String TestTitle;
            private String TestMessage;
            private boolean isShow = false;

            public boolean isShow() {
                return isShow;
            }

            public void setShow(boolean show) {
                isShow = show;
            }

            public ListBean(String aaa, String bbb) {
                TestTitle = aaa;
                TestMessage = bbb;
            }

            public String getTestTitle() {
                return TestTitle;
            }

            public void setTestTitle(String TestTitle) {
                this.TestTitle = TestTitle;
            }

            public String getTestMessage() {
                return TestMessage;
            }

            public void setTestMessage(String TestMessage) {
                this.TestMessage = TestMessage;
            }
        }
    }
}

5聋涨,對應(yīng)的適配器晾浴。適配器中根據(jù)對應(yīng)data中isShow參數(shù)顯示或者隱藏view,這還要多注意一點(diǎn)牍白,每個(gè)view都需要給他賦值脊凰,不然會(huì)發(fā)生數(shù)據(jù)沒有更新等不正常現(xiàn)象淹朋。

package com.mumu.jsrecyclerview2;

import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;

public class TestAdapter extends BaseQuickAdapter<TestEntity.ResultBean.ListBean, BaseViewHolder> {

    /**
     * 增加一個(gè)構(gòu)造方法笙各,便于沒有數(shù)據(jù)時(shí)候初始化適配器
     */
    public TestAdapter() {
        super(R.layout.item_test);
    }

    /**
     * 繼承BaseQuickAdapter后需要重寫的方法
     *
     * @param helper view持有者,為重用view而設(shè)計(jì)础芍,減少每次創(chuàng)建view的內(nèi)存消耗
     * @param data   我們的列表數(shù)據(jù)
     */
    @Override
    protected void convert(BaseViewHolder helper, TestEntity.ResultBean.ListBean data) {
        // TODO: 2019/1/10 需要詳細(xì)說明的點(diǎn):每一個(gè)子控件都要賦值操作杈抢,不然會(huì)造成數(shù)據(jù)混亂 ,如沒有給箭頭賦值仑性,在點(diǎn)擊
        // TODO: 2019/1/10 展開隱藏的時(shí)候箭頭的賦值會(huì)發(fā)生錯(cuò)亂(點(diǎn)擊第一個(gè)惶楼,第十一個(gè)數(shù)據(jù)也會(huì)更改)
        //將每一個(gè)需要賦值的id和對應(yīng)的數(shù)據(jù)綁定,綁定title和message
        helper.setText(R.id.tv_item_title, data.getTestTitle())
                .setText(R.id.tv_item_message, data.getTestMessage());
        //設(shè)置箭頭切換
        if(data.isShow()){
            helper.setImageResource(R.id.iv_item_arrow, R.mipmap.rw_arrow_1);
        }else {
            helper.setImageResource(R.id.iv_item_arrow, R.mipmap.rw_arrow_2);
        }
        //設(shè)置詳細(xì)消息布局隱藏
        helper.setGone(R.id.ll_item_message, data.isShow());
        //設(shè)置title的點(diǎn)擊監(jiān)聽
        helper.addOnClickListener(R.id.rl_item_title);
    }
}

6诊杆,對應(yīng)的適配器的每個(gè)子布局文件歼捐。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#ffffff"
    android:orientation="vertical">

    <RelativeLayout
        android:id="@+id/rl_item_title"
        android:layout_width="match_parent"
        android:layout_height="48dp">

        <TextView
            android:id="@+id/tv_item_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="16dp"
            android:text="--"
            android:textColor="#303030" />

        <ImageView
            android:id="@+id/iv_item_arrow"
            android:layout_width="13.3dp"
            android:layout_height="8dp"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_gravity="center_vertical"
            android:layout_marginRight="16dp"
            android:src="@mipmap/rw_arrow_2" />
    </RelativeLayout>

    <LinearLayout
        android:id="@+id/ll_item_message"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:visibility="gone"
        tools:visibility="visible">

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:layout_marginLeft="15dp"
            android:background="#EBEBEB" />

        <TextView
            android:id="@+id/tv_item_message"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:gravity="center_vertical"
            android:paddingLeft="15dp"
            android:paddingRight="15dp"
            android:text="--"
            android:textColor="#999999"
            android:textSize="14sp" />
    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="12dp"
        android:background="#F6F7F9" />
</LinearLayout>

7,對應(yīng)github地址

demo地址:https://github.com/mamumu/jsRecyclerView2

如果有發(fā)現(xiàn)錯(cuò)誤歡迎指正我及時(shí)修改晨汹,如果有好的建議歡迎留言豹储。如果覺得對你有幫助歡迎給小星星,謝謝淘这。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末剥扣,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子铝穷,更是在濱河造成了極大的恐慌钠怯,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件曙聂,死亡現(xiàn)場離奇詭異晦炊,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)宁脊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進(jìn)店門断国,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人朦佩,你說我怎么就攤上這事并思。” “怎么了语稠?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我仙畦,道長输涕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任慨畸,我火速辦了婚禮莱坎,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘寸士。我一直安慰自己檐什,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布弱卡。 她就那樣靜靜地躺著乃正,像睡著了一般。 火紅的嫁衣襯著肌膚如雪婶博。 梳的紋絲不亂的頭發(fā)上瓮具,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天,我揣著相機(jī)與錄音凡人,去河邊找鬼名党。 笑死,一個(gè)胖子當(dāng)著我的面吹牛挠轴,可吹牛的內(nèi)容都是我干的传睹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼岸晦,長吁一口氣:“原來是場噩夢啊……” “哼欧啤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起委煤,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤堂油,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后碧绞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體府框,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年讥邻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了迫靖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,115評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡兴使,死狀恐怖系宜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情发魄,我是刑警寧澤盹牧,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布俩垃,位于F島的核電站,受9級特大地震影響汰寓,放射性物質(zhì)發(fā)生泄漏口柳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一有滑、第九天 我趴在偏房一處隱蔽的房頂上張望跃闹。 院中可真熱鬧,春花似錦毛好、人聲如沸望艺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽找默。三九已至,卻和暖如春场靴,著一層夾襖步出監(jiān)牢的瞬間啡莉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工旨剥, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留咧欣,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓轨帜,卻偏偏與公主長得像魄咕,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子蚌父,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評論 2 355