Android RecyclerViewトップサスペンション実現



sticky.gif
考え方:
  • 各RecyclerViewのitemのレイアウト(以下itemUIという)には「吸頂テキスト」というレイアウト(以下StickyLayoutという)が含まれており、現在のitemAと前のitemBの吸頂情報が同じか否かに基づいてitemAのStickyLayoutを表示するか否かが決定される.
  • は、RecyclerViewのレイアウト(以下、wrapperUIという)の最上位部分を含む、偽のStickyLayout(以下、FakeStickyLayoutという)がある.
  • は、RecyclerViewのスクロールを傍受する、RecyclerViewのスクロール距離に基づいてFakeStickyLayoutが上または下にスクロールする距離を決定する.

  • コード解析
  • レイアウト:
  • wrapperUI.xml
    
      
    
        
    
    
    itemUI.xml
    
    
      
    
        
    
          
    
      ~~~~~~~
    
      
    
    

    この2つのレイアウトは特にありませんが、ポイントは
     
    

    このincludeラベルが参照するレイアウトは、吸頂のレイアウトであり、itemUIのStickyLayoutとwrapperUIのFakeStickyLayoutのレイアウトが一致することを保証している.
  • さらにRecyclerViewのAdapter:
  • // RecyclerView     item,     StickyLayout .
    public static final int FIRST_STICKY_VIEW = 1;
    // RecyclerView      item  ,   StickyLayout .
    public static final int HAS_STICKY_VIEW = 2;
    // RecyclerView     StickyLayout item.
    public static final int NONE_STICKY_VIEW = 3;
    
    if (position == 0) {     
        recyclerViewHolder.tvStickyHeader.setVisibility(View.VISIBLE);        
        recyclerViewHolder.tvStickyHeader.setText(stickyExampleModel.sticky);  
    
        //    item           ,    tag FIRST_STICKY_VIEW
        recyclerViewHolder.itemView.setTag(FIRST_STICKY_VIEW);
    
      } else {  
        //    item      item            ,      ,    tag HAS_STICKY_VIEW
        if (!TextUtils.equals(stickyExampleModel.sticky, stickyExampleModels.get(position - 1).sticky)) {  
          recyclerViewHolder.tvStickyHeader.setVisibility(View.VISIBLE);    
          recyclerViewHolder.tvStickyHeader.setText(stickyExampleModel.sticky);    
          recyclerViewHolder.itemView.setTag(HAS_STICKY_VIEW); 
    
        } else {       
          //       ,    tag NONE_STICKY_VIEW
          recyclerViewHolder.tvStickyHeader.setVisibility(View.GONE);       
          recyclerViewHolder.itemView.setTag(NONE_STICKY_VIEW);  
    
        }
      }
    // ContentDescription                
    recyclerViewHolder.itemView.setContentDescription(stickyExampleModel.sticky);
    
  • は半日話して、重点はついに
  • に来ました
    次のコードは直接持ってきて、何も変更しなくてもいいです.前提はあなたのadapterが上の3種類のマークに従って書いたことです.
    rvStickyExample.addOnScrollListener(new RecyclerView.OnScrollListener() {  
        @Override  
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {    
          super.onScrolled(recyclerView, dx, dy);
          //  RecyclerView   Item,      ,             ,      ,     
          int p = linearLayoutManager.findFirstVisibleItemPosition();
          if (p==0) {
              tvStickyHeaderView.setVisibility(View.GONE);
          }else {
              tvStickyHeaderView.setVisibility(View.VISIBLE);
          }
    
    
          //   RecyclerView item , RecyclerView getTop     5      item
          // (  2、3         ,      5   ),
          //       item,          ,
          //      StickyLayout              item   . 
          View stickyInfoView = recyclerView.findChildViewUnder(tvStickyHeaderView.getMeasuredWidth() / 2, 5);    
          if (stickyInfoView != null && stickyInfoView.getContentDescription() != null) {      
              tvStickyHeaderView.setText(String.valueOf(stickyInfoView.getContentDescription()));    
          }    
    
          //            FakeStickyLayout         RecyclerView item,
          //       item     StickyLayout translate    . 
          //      HAS_STICKY_VIEW NONE_STICKY_VIEW   tag,
          //      item StickyLayout    ,        FakeStickyLayout   . 
          View transInfoView = recyclerView.findChildViewUnder(
                             tvStickyHeaderView.getMeasuredWidth() / 2, tvStickyHeaderView.getMeasuredHeight() + 1);    
    
          if (transInfoView != null && transInfoView.getTag() != null) {      
            int transViewStatus = (int) transInfoView.getTag();      
            int dealtY = transInfoView.getTop() - tvStickyHeaderView.getMeasuredHeight();      
    
            //     item    StickyLayout,
            //       item getTop FakeStickyLayout           FakeStickyLayout. 
            //          ,    item getTop    0,         ,
            //          StickyLayout    ,      item       . 
            if (transViewStatus == StickyExampleAdapter.HAS_STICKY_VIEW) {              
              if (transInfoView.getTop() > 0) {          
                tvStickyHeaderView.setTranslationY(dealtY);        
              } else {          
                tvStickyHeaderView.setTranslationY(0);       
              }      
            } else if (transViewStatus == StickyExampleAdapter.NONE_STICKY_VIEW) {        
              //     item     StickyLayout,       FakeStickyLayout   . 
              tvStickyHeaderView.setTranslationY(0);      
            }    
          }  
        }
    });
    

    テキストリンク:https://www.jianshu.com/p/c596f2e6f587