自定義ViewGroup可折疊控件宿礁,類似CoordinatorLayout的效果

很多APP首頁都是采用頭部+列表的形式顯示钉寝,但是首頁的空間有限乍迄,這時就需要把頭部布局折疊起來了管引,參考效果如下:

UI圖

Google在Design庫22+上面增加了CoordinatorLayout+Behavior可以實(shí)現(xiàn)這種效y果,但是實(shí)現(xiàn)起來相對比較復(fù)雜闯两,下面我將用另一種方式實(shí)現(xiàn)褥伴。
工程已經(jīng)上傳aizuzi/FoldLayout,歡迎大家給start

效果圖

效果圖

實(shí)現(xiàn)步驟

第一步

我們自定義一個控件作為頭部顯示漾狼,實(shí)現(xiàn)復(fù)雜的折疊效果也是在該類完成重慢,在這里我先放一個ImageView作為示例,具體代碼如下

public class HeadView extends LinearLayout {
  private ImageView imageview;

  private float imagevViewY;
  public HeadView(Context context) {
    super(context);
    init();
  }

  public HeadView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
  }

  public HeadView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
  }

  /**
   * 初始化頭部布局
   */
  private void init() {
    imageview = new ImageView(getContext());
    imageview.setImageResource(R.mipmap.ic_launcher);
    addView(imageview,new LayoutParams(UnitUtil.dp2px(getContext(),80),UnitUtil.dp2px(getContext(),80)));

    setGravity(Gravity.CENTER);
    setBackgroundColor(getResources().getColor(R.color.colorAccent));
  }

  @Override
  protected void onLayout(boolean changed, int l, int t, int r, int b) {
    super.onLayout(changed, l, t, r, b);
    if(imagevViewY ==0)
    imagevViewY = imageview.getY();
  }

  /**
   * 拖動時改變控件的位置
   * @param percentage
   */
  public void offsetPixel(float percentage) {
    int viewHeight = getHeight();
    imageview.setY(imagevViewY+(int) ((viewHeight-imageview.getHeight())/2*percentage));
  }
}
第二步

下面的列表用一個自定義的RecyclerView顯示逊躁,如果是使用ListView或者GridView可以重寫dispatchTouchEvent方法來分發(fā)觸摸事件

public class CustomRecyclerView extends RecyclerView {
  private static final int TOUCH_IDLE = 0;
  private static final int TOUCH_DRAG_LAYOUT = 1;

  private int scrollMode;
  private float downY;
  private int minHeight;
  boolean isAtTop;

  public CustomRecyclerView(Context arg0) {
    super(arg0);
  }

  @Override
  public boolean dispatchTouchEvent(MotionEvent ev) {
    if (getTop() > minHeight) {
      getParent().requestDisallowInterceptTouchEvent(false);
      return false;
    }
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
      downY = ev.getRawY();
      isAtTop = isReadyForPullStart();
      scrollMode = TOUCH_IDLE;
      getParent().requestDisallowInterceptTouchEvent(true);
    } else if (ev.getAction() == MotionEvent.ACTION_MOVE) {
      if (scrollMode == TOUCH_IDLE) {
        float yDistance = Math.abs(downY - ev.getRawY());
        if (yDistance > 0) {
          scrollMode = TOUCH_DRAG_LAYOUT;
          if (downY < ev.getRawY() && isAtTop) {
            getParent().requestDisallowInterceptTouchEvent(false);
            return false;
          }
        }
      }
    }

    return super.dispatchTouchEvent(ev);
  }

  //傳入頭部布局的最小高度似踱,用于判斷分發(fā)觸摸事件
  public void setMinHeight(int minHeight) {
    this.minHeight = minHeight;
  }

  //判斷RecyclerView是否滾動到頂部
  protected boolean isReadyForPullStart() {
    if (getChildCount() <= 0)
      return false;
    View view = getChildAt(0);
    int firstVisiblePosition = getChildAdapterPosition(view);
    if (firstVisiblePosition == 0) {
      return view.getTop() >= getPaddingTop();
    } else {
      return false;
    }
  }
}
第三步

實(shí)現(xiàn)折疊效果的關(guān)鍵在這里,采用自定義ViewGroup來管理上面兩個空間的位置,在這里使用了support-v4包下的ViewDragHelper工具類來協(xié)調(diào)兩個空間的位置核芽。

核心代碼在ViewDragHelper.Callback回調(diào)里囚戚,ViewDragHelper已經(jīng)幫我們實(shí)現(xiàn)了拖拽控件,我們在回調(diào)里判斷到了最小的高度則停止拖拽轧简,并且通知子View實(shí)現(xiàn)自身的邏輯即可

  private class MDragCallback extends ViewDragHelper.Callback {

    @Override
    public void onViewPositionChanged(View changedView, int left, int top,
                                      int dx, int dy) {
      //控件正在拖拽中回調(diào)
    }

    @Override
    public boolean tryCaptureView(View child, int pointerId) {
      //是否需要捕獲child的拖動驰坊,為false則不拖動
      return true;
    }

    @Override
    public void onViewReleased(View releasedChild, float xvel, float yvel) {
      //手指移開屏幕,這里需要做回彈的動畫
    }

    @Override
    public int clampViewPositionVertical(View child, int top, int dy) {
     //返回拖動后控件的坐標(biāo)哮独,child為拖動中的子控件
      return top;
    }
  }

最后

第一次寫教程還有很多地方寫得不是很明白拳芙,還望大家體諒,如果大家有問題可以在后面留言或者發(fā)簡信給我皮璧,我會盡快回復(fù)舟扎。

最后再重復(fù)一下,工程已經(jīng)全部上傳aizuzi/FoldLayout恶导,歡迎大家去給start

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末浆竭,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子惨寿,更是在濱河造成了極大的恐慌邦泄,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件裂垦,死亡現(xiàn)場離奇詭異顺囊,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蕉拢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進(jìn)店門特碳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人晕换,你說我怎么就攤上這事午乓。” “怎么了闸准?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵益愈,是天一觀的道長。 經(jīng)常有香客問我夷家,道長蒸其,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任库快,我火速辦了婚禮摸袁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘义屏。我一直安慰自己靠汁,他們只是感情好蜂大,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蝶怔,像睡著了一般县爬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上添谊,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天,我揣著相機(jī)與錄音察迟,去河邊找鬼斩狱。 笑死遣妥,一個胖子當(dāng)著我的面吹牛则奥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播恼布,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼概荷,長吁一口氣:“原來是場噩夢啊……” “哼秕岛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起误证,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤继薛,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后愈捅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體遏考,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年蓝谨,在試婚紗的時候發(fā)現(xiàn)自己被綠了灌具。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡譬巫,死狀恐怖咖楣,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情芦昔,我是刑警寧澤诱贿,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站烟零,受9級特大地震影響瘪松,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜锨阿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一宵睦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧墅诡,春花似錦壳嚎、人聲如沸桐智。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽说庭。三九已至,卻和暖如春郑趁,著一層夾襖步出監(jiān)牢的瞬間刊驴,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工寡润, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留捆憎,地道東北人。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓梭纹,卻偏偏與公主長得像躲惰,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子变抽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評論 2 351

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