RecyclerView筆記

一. RecyclerView的基礎(chǔ)用法

  1. 添加依賴
compile 'com.android.support:recyclerview-v7:25.2.0'
  1. xml使用布局
<!--下拉刷新控件-->
    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swipe_refresh_linear_recycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        
        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view_linear"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

        </android.support.v7.widget.RecyclerView>

    </android.support.v4.widget.SwipeRefreshLayout>
  1. 新建recycler_item的布局(recyclerview中的item的布局,此處的布局是CardView嵌套了ImageView)
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    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"
    app:cardElevation="@dimen/cardview_default_elevation"
    app:cardCornerRadius="@dimen/cardview_default_radius"
    android:layout_margin="8dp">

    <ImageView
        android:id="@+id/iv_meizi"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"/>
</android.support.v7.widget.CardView>
  1. 新建Adapter
public class LinearRecyclerAdapter extends RecyclerView.Adapter<LinearRecyclerAdapter.ViewHolder> {

    private Context mContext;
    private List<Meizi> mMeiziList;

    /*構(gòu)造函數(shù),進(jìn)行初始化(一般傳入context和數(shù)據(jù)列表)*/
    public LinearRecyclerAdapter(Context context,List<Meizi> meiziList) {
        mContext = context;
        mMeiziList = meiziList;
    }

    /*創(chuàng)建ViewHolder*/
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(mContext).inflate(R.layout.recycler_item_linear_recycler,parent,false);
        return new ViewHolder(view);
    }

    /*數(shù)據(jù)綁定到ViewHolder*/
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Meizi meizi = mMeiziList.get(position);
        Picasso.with(mContext).load(meizi.getImageUrl()).into(holder.mImageView);
    }

    /*item的數(shù)量,一般就是數(shù)據(jù)List的大小*/
    @Override
    public int getItemCount() {
        return mMeiziList.size();
    }

    /*內(nèi)部類ViewHolder*/
    class ViewHolder extends RecyclerView.ViewHolder {
        private ImageView mImageView;
        ViewHolder(View itemView) {
            super(itemView);
            mImageView = (ImageView) itemView.findViewById(R.id.iv_meizi);
        }
    }

    /*添加item的函數(shù)*/
    public void addItem(Meizi meizi, int position) {
        mMeiziList.add(position, meizi);
        notifyItemInserted(position);
    }

    /*滑動(dòng)刪除會(huì)調(diào)用的函數(shù)*/
    public void removeItem(final int position) {
        final Meizi removed=mMeiziList.get(position);
        mMeiziList.remove(position);
        notifyItemRemoved(position);
        Toast.makeText(mContext,"你刪除了第"+position+"個(gè)item",Toast.LENGTH_SHORT).show();
    }
}
  1. 實(shí)例化RecyclerView,設(shè)置布局管理器和Adapter
        mRecyclerView = (RecyclerView) mRootView.findViewById(R.id.recycler_view_linear);//初始化recyclerview
        mLayoutManager = new LinearLayoutManager(getContext());//初始化布局管理器
        mRecyclerView.setLayoutManager(mLayoutManager);//設(shè)置布局管理器
  1. 獲取數(shù)據(jù),封裝到List中罗捎,實(shí)例化Adapter,給RecyclerView設(shè)置Adapter

二. 下拉刷新的實(shí)現(xiàn)

  1. 實(shí)例化SwipeRefreshLayout
/*初始化下拉刷新控件*/
mSwipeRefreshLayout = (SwipeRefreshLayout) mRootView.findViewById(R.id.swipe_refresh_linear_recycler);
  1. 下拉刷新監(jiān)聽
        /*swipeRefreshLayout刷新監(jiān)聽*/
        mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                //下拉刷新之后要進(jìn)行的操作拉盾,一般是重新加載數(shù)據(jù)
                new GetMeiziTask().execute("http://gank.io/api/data/福利/10/1 ");
            }
        });
  1. 刷新之后記得調(diào)用mSwipeRefreshLayout.setRefreshing(false);取消顯示刷新的按鈕桨菜,每次在刷新之前可以調(diào)用mSwipeRefreshLayout.setRefreshing(true);顯示刷新按鈕(一般在AsyncTask的onPreExecute中)

三. 滑動(dòng)刪除和長按交換位置的實(shí)現(xiàn)

  1. 原理
  • 滑動(dòng)刪除就是監(jiān)聽滑動(dòng)事件,然后在回調(diào)方法中捉偏,將數(shù)據(jù)list中的對(duì)應(yīng)元素刪除
  • 長按交換位置就是長按事件倒得,然后在回調(diào)方法中,將數(shù)據(jù)list中的對(duì)應(yīng)元素進(jìn)行移動(dòng)
  1. 使用方法
  • 實(shí)例化ItemTouchHelper類夭禽,在回調(diào)方法中實(shí)現(xiàn)滑動(dòng)刪除
/*item觸摸助手類霞掺,用于實(shí)現(xiàn)滑動(dòng)刪除等操作*/
        mItemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.Callback() {

            //用于設(shè)置拖拽和滑動(dòng)的方向
            @Override
            public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
                int dragFlags=0,swipeFlags=0;
                if(recyclerView.getLayoutManager() instanceof StaggeredGridLayoutManager ||recyclerView.getLayoutManager() instanceof GridLayoutManager){
                    //網(wǎng)格式布局有4個(gè)方向
                    dragFlags=ItemTouchHelper.UP|ItemTouchHelper.DOWN|ItemTouchHelper.LEFT|ItemTouchHelper.RIGHT;
                }else if(recyclerView.getLayoutManager() instanceof LinearLayoutManager){
                    //線性式布局有2個(gè)方向
                    dragFlags=ItemTouchHelper.UP|ItemTouchHelper.DOWN;

                    swipeFlags = ItemTouchHelper.START|ItemTouchHelper.END; //設(shè)置側(cè)滑方向?yàn)閺膬蓚€(gè)方向都可以
                }
                return makeMovementFlags(dragFlags,swipeFlags);//swipeFlags 為0的話item不滑動(dòng)
            }

            //長摁item拖拽時(shí)會(huì)回調(diào)這個(gè)方法
            @Override
            public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
                /*int from=viewHolder.getAdapterPosition();
                int to=target.getAdapterPosition();
                Meizi moveItem=mMeiziList.get(from);
                mMeiziList.remove(from);
                mMeiziList.add(to,moveItem);//交換數(shù)據(jù)鏈表中數(shù)據(jù)的位置
                mLinearRecyclerAdapter.notifyItemMoved(from,to);//更新適配器中item的位置*/
                int from=viewHolder.getAdapterPosition();
                int to=target.getAdapterPosition();
                Collections.swap(mMeiziList,from,to);
                mLinearRecyclerAdapter.notifyItemMoved(from,to);
                return true;
            }

            /*滑動(dòng)刪除*/
            @Override
            public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
                mLinearRecyclerAdapter.removeItem(viewHolder.getAdapterPosition());
            }
        });
  • 將ItemTouchHelper與RecyclerView綁定
mItemTouchHelper.attachToRecyclerView(mRecyclerView);//觸摸事件關(guān)聯(lián)到RecyclerView

四. 簡單的RecyclerItem動(dòng)畫的實(shí)現(xiàn)

/*設(shè)置item加載或移除時(shí)的動(dòng)畫*/
mRecyclerView.setItemAnimator(new DefaultItemAnimator());

五. item的點(diǎn)擊事件實(shí)現(xiàn)

  1. 在Adapter里面實(shí)現(xiàn)事件監(jiān)聽
  • 在ViewHolder里直接給控件添加監(jiān)聽事件
ViewHolder(View itemView) {
            super(itemView);
            mImageView = (ImageView) itemView.findViewById(R.id.iv_meizi);
            mImageView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(mContext,"You clicked item "+getAdapterPosition(),Toast.LENGTH_SHORT).show();
                }
            });
        }
  • 在onBindViewHolder方法里給控件添加監(jiān)聽事件
@Override
    public void onBindViewHolder(ViewHolder holder, final int position) {
        Meizi meizi = mMeiziList.get(position);
        Picasso.with(mContext).load(meizi.getImageUrl()).into(holder.mImageView);
        /*holder.mImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(mContext,"You clicked item "+holder.getAdapterPosition(),Toast.LENGTH_SHORT).show();
            }
        });*/
    }
  1. 在調(diào)用的地方實(shí)現(xiàn)回調(diào)的監(jiān)聽和處理
  • Adapter實(shí)現(xiàn)回掉接口,在調(diào)用處進(jìn)行調(diào)用

六. 上拉加載

  1. 上拉加載就是先設(shè)置onScrollListener讹躯,在listener方法里面進(jìn)行判斷然后加載數(shù)據(jù)菩彬,加載數(shù)據(jù)的原理是獲取新的數(shù)據(jù)然后添加到List集合中,然后再調(diào)用Adapter的notifyDataSetChanged通知更新數(shù)據(jù)潮梯。

七. 四大角色

  1. RecyclerView

RecyclerView就是一個(gè)控件骗灶,和普通控件一樣,只不過他的作用是用來展示列表秉馏,回收和定位屏幕上的view

  1. Adapter

適配器耙旦,用來創(chuàng)建RecyclerView的界面(ViewHolder),加載數(shù)據(jù)到界面上萝究,當(dāng)RecyclerView需要顯示view時(shí)免都,就會(huì)去找它的adapter锉罐。具體過程如下:

  • 調(diào)用adapter的getIemCount()方法,詢問列表對(duì)象的總個(gè)數(shù)
  • 調(diào)用adapter的createViewHolder()方法绕娘,創(chuàng)建ViewHolder和要顯示的視圖
  • 傳入ViewHolder和要加載的視圖位置脓规,調(diào)用adapter的onBindViewHolder()方法,為視圖綁定數(shù)據(jù)
    每當(dāng)需要加載一個(gè)item的時(shí)候就會(huì)調(diào)用以上方法险领,直到需要加載的item都加載完成
  1. LayoutManager

用來定義RecyclerView的顯示規(guī)則(如定位列表項(xiàng)抖拦,定義屏幕的滾動(dòng)行為等),正因?yàn)橛蠰ayoutManager的存在舷暮,才使得RecyclerView顯示變得更靈活

  1. ViewHolder

ViewHolder在這里用來容納每個(gè)item里面的控件引用,然后執(zhí)行findViewById方法噩茄。因?yàn)閞ecyclerView里面的每個(gè)item都有相同的控件引用下面,所以使用ViewHolder之后就可以減少findViewById方法的調(diào)用從而提高性能。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末绩聘,一起剝皮案震驚了整個(gè)濱河市沥割,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌凿菩,老刑警劉巖机杜,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異衅谷,居然都是意外死亡椒拗,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門获黔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蚀苛,“玉大人,你說我怎么就攤上這事玷氏《挛矗” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵盏触,是天一觀的道長渗蟹。 經(jīng)常有香客問我,道長赞辩,這世上最難降的妖魔是什么雌芽? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮诗宣,結(jié)果婚禮上膘怕,老公的妹妹穿的比我還像新娘。我一直安慰自己召庞,他們只是感情好岛心,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布来破。 她就那樣靜靜地躺著,像睡著了一般忘古。 火紅的嫁衣襯著肌膚如雪徘禁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天髓堪,我揣著相機(jī)與錄音送朱,去河邊找鬼。 笑死干旁,一個(gè)胖子當(dāng)著我的面吹牛驶沼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播争群,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼回怜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了换薄?” 一聲冷哼從身側(cè)響起玉雾,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎轻要,沒想到半個(gè)月后复旬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡冲泥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年驹碍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凡恍。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡幸冻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出咳焚,到底是詐尸還是另有隱情洽损,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布革半,位于F島的核電站碑定,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏又官。R本人自食惡果不足惜延刘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望六敬。 院中可真熱鬧碘赖,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至撼班,卻和暖如春歧匈,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背砰嘁。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來泰國打工件炉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人矮湘。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓斟冕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親缅阳。 傳聞我的和親對(duì)象是個(gè)殘疾皇子宫静,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,133評(píng)論 25 707
  • layout: posttitle: "新控件筆記"date: 2016-08-16 12:16:58 +0800...
    qianxL閱讀 627評(píng)論 0 0
  • 感謝有你的出現(xiàn),我的世界才不至于特別昏暗券时。 喜歡一個(gè)人是什么感覺。 在我還未遇到你之前伏伯,那種感覺對(duì)我來說...
    南城北巷花已開閱讀 323評(píng)論 0 0
  • 千里之堤潰于蟻穴橘洞,我們固化做某件事時(shí),一定要堅(jiān)守说搅!因?yàn)橹灰幸淮畏潘烧ㄔ妫瑥拇舜竽X就記住了這個(gè)放松的感覺,當(dāng)我們?cè)僮鲞@...
    小朱的飛刀閱讀 226評(píng)論 0 0
  • #你好
    fd棉花狼閱讀 119評(píng)論 0 0