android RecyclerView

来源:https://www.cnblogs.com/94xiyang/archive/2018/08/22/9518711.html
-Advertisement-
Play Games

引用 在項目的build.gradle添加依賴 RecyclierView使用的基本方法 recyclerView.setAdapter(); 添加適配器(必須) recyclerView.setLayoutManager(); 選擇一種佈局(必須) recyclerAdapter.setHeade ...


引用

在項目的build.gradle添加依賴

compile 'com.android.support:recyclerview-v7:23.4.0'

RecyclierView使用的基本方法

recyclerView.setAdapter(); 添加適配器(必須)

recyclerView.setLayoutManager(); 選擇一種佈局(必須)

recyclerAdapter.setHeaderView(); 添加頭佈局

recyclerAdapter.setFooterView(); 添加底部佈局

recyclerView.setItemAnimator(new DefaultItemAnimator()); 添加預設動畫

recyclerView.addItemDecoration(); 添加分割線

Layout Manager佈局管理器

1.三種佈局管理器:

new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false) 以垂直或者水平列表方式展示Item,第三個參數是否顛倒數據顯示

new GridLayoutManager(this,4)  以網格方式展示Item,第二個參數代表列數

new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.HORIZONTAL)  以瀑布流方式展示Item,第一個參數代表列數

2.常用方法

canScrollHorizontally();//能否橫向滾動
canScrollVertically();//能否縱向滾動
scrollToPosition(int position);//滾動到指定位置
setOrientation(int orientation);//設置滾動的方向
getOrientation();//獲取滾動方向
findViewByPosition(int position);//獲取指定位置的Item View
findFirstCompletelyVisibleItemPosition();//獲取第一個完全可見的Item位置
findFirstVisibleItemPosition();//獲取第一個可見Item的位置
findLastCompletelyVisibleItemPosition();//獲取最後一個完全可見的Item位置
findLastVisibleItemPosition();//獲取最後一個可見Item的位置

 Adapter適配器模板

RecyclerView必須自定義適配器,並且自己創建事件監聽,佈局和數據的綁定順序,每個Item都會執行一遍:getIItemViewType(綁定類型) > onCreateViewHolder(選擇佈局類型) > onBindViewHolder(綁定數據)

notifyItemInserted(position);插入一個item

notifyItemRemoved(position); 移除一個item

notifyItemChanged(position) 刷新item

public class DataRecyclerAdapter extends RecyclerView.Adapter<DataRecyclerAdapter.MyViewHolder>{
    private List<String> list;
    private Context context;
    private List<Integer> mHeights;
    private static int TYPE_TITLE=0;
    private static int TYPE_FOOTER=1;
    private static int TYPE_CONTENT =2;
    private View mHeaderView;
    private View mFooterView;

    public DataRecyclerAdapter(Context context, List<String> list) {
        this.list=list;
        mHeights = new ArrayList<>();
        this.context=context;
    }

    //根據不同的類型適應不用的佈局
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if(mHeaderView != null && viewType == TYPE_TITLE) {
            return new MyViewHolder(mHeaderView);
        }
        if(mFooterView != null && viewType == TYPE_FOOTER) {
            return new MyViewHolder(mFooterView);
        }
        return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.options_item3,parent,false));
    }

    //給item分佈不同的類型
    @Override
    public int getItemViewType(int position) {
        if (position == 0){
            return TYPE_TITLE;
         }else if(position==list.size()){
            return TYPE_FOOTER;
        }else{
            return TYPE_CONTENT;
        }
    }

    public View getHeaderView() {
        return mHeaderView;
    }
    //添加自定義的頭部
    public void setHeaderView(View headerView) {
        mHeaderView = headerView;
        notifyItemInserted(0);
    }

    public View getFooterView() {
        return mFooterView;
    }
    //添加自定義底部
    public void setFooterView(View footerView) {
        mFooterView = footerView;
        notifyItemInserted(list.size()+1);
    }
    //主體佈局
    @Override
    public void onBindViewHolder(final MyViewHolder holder, int position) {
        if(getItemViewType(position) != TYPE_CONTENT) {
            return;
        }
            holder.textView.setText(list.get(position-1));

        if (mOnItemClickLitener != null){
            holder.itemView.setOnClickListener(new View.OnClickListener(){
                @Override
                public void onClick(View v){
                    int pos = holder.getLayoutPosition();
                    mOnItemClickLitener.onItemClick(holder.itemView, pos);
                }
            });

            holder.itemView.setOnLongClickListener(new View.OnLongClickListener(){
                @Override
                public boolean onLongClick(View v){
                    int pos = holder.getLayoutPosition();
                    mOnItemClickLitener.onItemLongClick(holder.itemView, pos);
                    return true;
                }
            });
        }
    }

    //獲取item總數
    @Override
    public int getItemCount() {
         if(mFooterView !=null){
            return list.size()+1;
        }else {
            return list.size();
        }
    }
    //監聽器介面
    public interface OnItemClickLitener{
        void onItemClick(View view, int position);
        void onItemLongClick(View view , int position);
    }

    private OnItemClickLitener mOnItemClickLitener;

    public void setOnMyItemClickLitener(OnItemClickLitener mOnItemClickLitener) {
        this.mOnItemClickLitener = mOnItemClickLitener;
    }

   //頭和底部的佈局
    class MyViewHolder extends RecyclerView.ViewHolder {
        private TextView textView;
        MyViewHolder(View itemView) {
            super(itemView);
            if (itemView == mHeaderView||itemView == mFooterView){
                return;
            }
            textView= (TextView) itemView.findViewById(R.id.options_tv);
            textView.setText("UUU");
        }
    }
    //模擬新增的數據
    public void addData(int position) {
        list.add(position, "Insert 數據");
        notifyItemInserted(position+1);
        Toast.makeText(context,""+list.size(),Toast.LENGTH_SHORT).show();
    }
    //移除一個佈局
    public void removeData(int position) {
        list.remove(position);
        notifyItemRemoved(position);
    }

實例

private void initDataRecyclerAdapter(){
    recyclerAdapter=new DataRecyclerAdapter(this,mData);
    //佈局管理器
    recyclerView.setLayoutManager( new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
    //分割線
    recyclerView.addItemDecoration(new DividerItemDecoration(this,
            DividerItemDecoration.HORIZONTAL));
    //使用預設動畫
    recyclerView.setItemAnimator(new DefaultItemAnimator());
    //不使用預設的佈局類型,添加自定義頭部佈局
    recyclerAdapter.setHeaderView(LayoutInflater.from(this).inflate(R.layout.options_title, recyclerView, false));
    //不使用預設的佈局類型,添加自定義底部佈局
    LayoutInflater inflater= LayoutInflater.from(this);
    View footerView = inflater.inflate(R.layout.options_footer, null);
    recyclerAdapter.setFooterView(footerView);
    //底部佈局事件,增加一個item
    footerView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Toast.makeText(MainActivity.this,"展開",Toast.LENGTH_SHORT).show();
            recyclerAdapter.addData(mData.size());
        }
    });
    recyclerView.setAdapter(recyclerAdapter);
    recyclerAdapter.setOnMyItemClickLitener(new DataRecyclerAdapter.OnItemClickLitener() {
        //item的點擊事件,移除一個item
        @Override
        public void onItemClick(View view, int position) {
            recyclerAdapter.removeData(position);
            Toast.makeText(MainActivity.this,""+mData.size(),Toast.LENGTH_SHORT).show();
        }
        //item的長按事件,顯示item下標
        @Override
        public void onItemLongClick(View view, int position) {
            Toast.makeText(MainActivity.this,"第"+position+"個",Toast.LENGTH_SHORT).show();
        }
    });
}
//模擬數據源
private void addData(){
    mData= new ArrayList<>();
    for (int i=1;i<20;i++) {
        mData.add("數據"+i+"個");
    }
}

ItemTouchHelper滑動拖拽

1.getMovementFlags

用於設置是否處理拖拽事件和滑動事件,如果是列表類型的,拖拽只有ItemTouchHelper.UP、ItemTouchHelper.DOWN兩個方向
如果是網格類型的,拖拽則有UP、DOWN、LEFT、RIGHT四個方向
最後,需要調用return makeMovementFlags(dragFlags, swipeFlags);將設置的標誌位return回去

   @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        if (recyclerView.getLayoutManager() instanceof GridLayoutManager) {
            final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
           //網格佈局不處理滑動事件
            final int swipeFlags = 0;
        } else {
            final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
            //列表佈局不處理滑動事件
            final int swipeFlags = 0; 
        }
        return makeMovementFlags(dragFlags, swipeFlags);
    }

2.onMove

長按item的時候就會進入拖拽,併在拖拽過程中不斷回調
viewHolder.getAdapterPosition();  得到拖動ViewHolder的position
target.getAdapterPosition();  得到目標ViewHolder的position

@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
    int fromPosition = viewHolder.getAdapterPosition();
    int toPosition = target.getAdapterPosition();
    if (fromPosition < toPosition) {
        //分別把中間所有的item的位置重新交換
        for (int i = fromPosition; i < toPosition; i++) {
            Collections.swap(mData, i, i + 1);
        }
    } else {
        for (int i = fromPosition; i > toPosition; i--) {
            Collections.swap(mData, i, i - 1);
        }
    }
    //執行移動操作
    recyclerAdapter.notifyItemMoved(fromPosition, toPosition);
    return true;
}

3.onSwiped

移動item的時候就會進入滑動併在滑動過程中不斷回調
viewHolder.getAdapterPosition();//得到拖動ViewHolder的position
target.getAdapterPosition();//得到目標ViewHolder的position

@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
    int position = viewHolder.getAdapterPosition();
    //執行移除操作
    mData.remove(position);
    recyclerAdapter.notifyItemRemoved(position);
}

4.onChildDraw

滑動時會不斷回調,返回X、Y的坐標

@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
    super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
    if(actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
        //滑動時改變Item的透明度
        final float alpha = 1 - Math.abs(dX) / (float)viewHolder.itemView.getWidth();
        viewHolder.itemView.setAlpha(alpha);
        viewHolder.itemView.setTranslationX(dX);
    }
}

5.onSelectedChanged

當選中Item時候會調用該方法

 @Override
    public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
            //選中item開始拖拽時,改變顏色
            viewHolder.itemView.setBackgroundColor(Color.blue);
        
    }

6.clearView

item被放開或者動畫完成的回調

 @Override
 public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
     super.clearView(recyclerView, viewHolder);
     //拖拽或滑動完成時,變回白色
     viewHolder.itemView.setBackgroundColor(0);
 }

7.isLongPressDragEnabled

是否支持拖拽操作,預設是支持返回true。如果想指定item可以拖拽,需要重寫返回false,在item的長按監聽事件里調用startDrag(ViewHolder)開啟拖拽

 @Override
 public boolean isLongPressDragEnabled() {
   return true;
 }

8.isItemViewSwipeEnabled

是否支持滑動操作,預設是支持返回true。如果想指定item可以滑動,需要重寫返回false,在item的點擊事件里調用startSwipe(ViewHolder)開啟滑動。

@Override
public boolean isItemViewSwipeEnabled() {
    return true;
}

9.實例

ItemTouchHelper.Callback mCallback2 = new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP|ItemTouchHelper.DOWN,ItemTouchHelper.RIGHT) {
   
    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
        int fromPosition = viewHolder.getAdapterPosition();
        int toPosition = target.getAdapterPosition();
        if (fromPosition < toPosition) {
            //分別把中間所有的item的位置重新交換
            for (int i = fromPosition; i < toPosition; i++) {
                Collections.swap(mData, i, i + 1);
            }
        } else {
            for (int i = fromPosition; i > toPosition; i--) {
                Collections.swap(mData, i, i - 1);
            }
        }
        recyclerAdapter.notifyItemMoved(fromPosition, toPosition);
        return true;
    }

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
        int position = viewHolder.getAdapterPosition();
        mData.remove(position);
        recyclerAdapter.notifyItemRemoved(position);
    }

    @Override
    public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
        if(actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
            //滑動時改變Item的透明度
            final float alpha = 1 - Math.abs(dX) / (float)viewHolder.itemView.getWidth();
            viewHolder.itemView.setAlpha(alpha);
            viewHolder.itemView.setTranslationX(dX);
        }
    }

    @Override
    public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
        super.onSelectedChanged(viewHolder, actionState);

    }

    @Override
    public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        super.clearView(recyclerView, viewHolder);
        viewHolder.itemView.setBackgroundColor(0);
    }
};

//添加ItemTouchHelper介面
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(mCallback);

//指定RecyclerView
itemTouchHelper.attachToRecyclerView(recyclerView);

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • --Oracle使用的是用戶管理模式--意味著,Oracle的數據使用用戶來分割 --以後開發,我們需要每個項目都需要使用一個用戶 --所以:一個數據文件是可以放多個用戶的數據的。但是我們開發從數據的維護而已,是不希望--一個文件放多個用戶的數據的。這樣會導致相互影響 --數據文件是通過表空間來創建 ...
  • [toc] 問題 MySQL5.6 新建本地可以登錄的用戶,但在本地始終登錄不上,不存在的用戶卻能登錄成功 分析 1、本是以ip地址進行登錄的,錯誤信息報的是Access denied for user 'admin'@'slave58',自動進行了DNS解析,解析成了主機名,skip name r ...
  • Code: 參考(轉載): https://blog.csdn.net/qq_36663951/article/details/73176103 ...
  • 開發都離不開數據,對資料庫的熟悉程度可以為我們省去很多麻煩,我們必須先瞭解一下資料庫。 一個事務本質上有四個特點ACID: Atomicity原子性 Consistency一致性 Isolation隔離性 Durability耐久性 悲觀鎖和樂觀鎖的區別 悲觀鎖(Pessimistic Lock): ...
  • 簡述在Windows操作系統下搭建ADT和eclipse安卓(Android)開發環境的方法。 ...
  • Android ConstraintLayout詳解 https://www.jianshu.com/p/a8b49ff64cd3 1. 概述 在本篇文章中,你會學習到有關ConstraintLayout -- 一種構建於彈性Constraints(約束)系統的新型Android Layout。最終 ...
  • 在C語言中,編程都是面向過程的編程,每一個代碼塊都嚴格按照從上至下的順序執行,在代碼塊之間同樣也是這樣, 但是在OC中往往不是這樣,OC和C++、java等語言一樣,都是面向對象的編程語言,在代碼的執行上有很大的跳躍性。 OC是C語言的超集,對C語言所有的功能進行了封裝,例如,OC對C語言的字元串進 ...
  • 一個老鳥發的公司內部整理的 Android 學習路線圖 2017年09月12日 17:13:27 閱讀數:20449 一個老鳥發的公司內部整理的 Android 學習路線圖 2017年09月12日 17:13:27 閱讀數:20449 一個老鳥發的公司內部整理的 Android 學習路線圖 一個老鳥 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...