欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android模仿知乎的回答詳情頁的動畫效果

 更新時間:2016年02月22日 10:25:23   作者:一葉飄舟  
這篇文章主要介紹了Android模仿“知乎”的回答詳情頁的動畫效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下

 廢話不多說,咱們第一篇文章就是模仿“知乎”的回答詳情頁的動畫效果,先上個原版的效果圖,咱們就是要做出這個效果


    在實現(xiàn)之前,我們先根據(jù)上面的動畫效果,研究下需求,因為gif幀數(shù)有限,所以不是很連貫,推薦你直接下載一個知乎,找到這個界面自己玩玩
☞當文章往上移動到一定位置之后,最上面的標題欄Bar和問題布局Title是會隱藏的,回答者Author布局不會隱藏
☞當文章往下移動移動到一定位置之后,原先隱藏的標題欄Bar和問題布局Title會下降顯示
☞當文章往上移動的時候,下部隱藏的Tools布局會上升顯示
☞當文章往下移動的時候,如果Tools布局是顯示的,則隱藏
☞當標題欄Bar和問題布局Title下降顯示的時候,Title是從Bar的下面出來的,有個遮擋的效果
☞當快速滑動內(nèi)容到達底部的時候,隱藏的Tools會顯示出來
☞當快速滑動內(nèi)容到頂部的時候,隱藏的Bar和Title也會顯示出來

    不分析不知道,這樣一個簡單地效果,經(jīng)過分析需要完成不少東西呢,那么下面根據(jù)要實現(xiàn)的需求,咱們分析一下解決方案。
    在做這種仿界面之前,我們可以使用ADT帶的View Hierarchy工具看一下“知乎”原生是怎么實現(xiàn)的


    從右邊的分析圖可以看出,知乎的這個界面,內(nèi)容用的WebView,這很正常,因為用戶的回答里面格式比較復(fù)雜,用WebView是最好的解決方案,而標題欄是一個VIew,是ActionBar還是自定義View呢,不得而知,下面是就是一個LinearLayout包了4個ToggleButton,布局很簡單,我們沒有WebView,所以使用ScrollView代替,上面的布局直接ImageView了,設(shè)置個src,模擬一個布局。
    其實布局很簡單,咱們一個效果一個效果的來實現(xiàn)。
    首先是下面的Tools如何顯示和隱藏呢?當然是用動畫了!什么動畫呢?能實現(xiàn)的有屬性動畫和幀動畫,屬性動畫能夠真實的改變View的屬性,幀動畫只是視覺上移動了,View的實際屬性并不改變,這兩種都可以,我們這里使用屬性動畫

/** 
  * 顯示工具欄 
  */ 
 private void showTools() { 
 
  ObjectAnimator anim = ObjectAnimator.ofFloat(img_tools, "y", img_tools.getY(), 
    img_tools.getY() - img_tools.getHeight()); 
  anim.setDuration(TIME_ANIMATION); 
  anim.start(); 
 
  isToolsHide = false; 
 } 
 
 /** 
  * 隱藏工具欄 
  */ 
 private void hideTools() { 
 
  ObjectAnimator anim = ObjectAnimator.ofFloat(img_tools, "y", img_tools.getY(), 
    img_tools.getY() + img_tools.getHeight()); 
  anim.setDuration(TIME_ANIMATION); 
  anim.start(); 
 
  isToolsHide = true; 
 
 } 

    那么什么時候調(diào)用呢?從上面的需求分析中,我們知道,用戶手指下拉的時候,Tools顯示,反之隱藏,那么我們就可以監(jiān)聽ScrollView的onTouch,判斷手指方向,實現(xiàn)動畫效果的調(diào)用

mScroller.setOnTouchListener(new View.OnTouchListener() { 
   @Override 
   public boolean onTouch(View v, MotionEvent event) { 
 
 
    switch (event.getAction()) { 
 
     case MotionEvent.ACTION_DOWN: 
      lastY = event.getY(); 
      break; 
     case MotionEvent.ACTION_MOVE: 
 
      float disY = event.getY() - lastY; 
 
      //垂直方向滑動 
      if (Math.abs(disY) > viewSlop) { 
       //是否向上滑動 
       isUpSlide = disY < 0; 
 
       //實現(xiàn)底部tools的顯示與隱藏 
       if (isUpSlide) { 
        if (!isToolsHide) 
         hideTools(); 
       } else { 
        if (isToolsHide) 
         showTools(); 
       } 
      } 
 
      break; 
    } 
 
    return false; 
   } 
  }); 

     用變量isToolsHide放置代碼重復(fù)調(diào)用。

    下面的Tools的問題解決了,我們再看一下上面的布局動畫如何來實現(xiàn)。上面的思路和下面一樣,也是通過屬性動畫,完成位置的移動,移動的布局有Bar、Title和根布局。為什么答題人布局Author不移動呢?因為根布局必須移動,否則就會擋住下面的文字內(nèi)容,根布局的移動會讓子布局都跟著移動,所以只移動根布局即可。
    對了,為了更大范圍的現(xiàn)實文本,“知乎”的WebView是占據(jù)整個布局的,其他布局都是在根布局FrameLayout里面,所以,在首次加載的時候,下面的文本在開頭需要留出一定的間隔,防止被遮擋,當上面的布局隱藏之后,就沒有問題了。
    在簡單分析之后,我再給出實現(xiàn)的布局的代碼

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:background="@android:color/white" 
 > 
 
 
 <com.socks.zhihudetail.MyScrollView 
  android:id="@+id/scroller" 
  android:layout_width="match_parent" 
  android:layout_height="wrap_content" 
  > 
 
  <TextView 
   android:layout_width="match_parent" 
   android:layout_height="match_parent" 
   android:textSize="16sp" 
   android:textColor="@android:color/black" 
   android:text="@string/hello_world"/> 
 
 </com.socks.zhihudetail.MyScrollView> 
 
 
 <FrameLayout 
  android:id="@+id/ll_top" 
  android:layout_width="match_parent" 
  android:layout_height="wrap_content" 
  android:background="@android:color/white" 
  android:orientation="vertical" 
  android:layout_gravity="top"> 
 
  <ImageView 
   android:id="@+id/img_author" 
   android:layout_width="match_parent" 
   android:layout_height="80dp" 
   android:scaleType="fitXY" 
   android:src="@drawable/bg_author"/> 
 
  <TextView 
   android:id="@+id/tv_title" 
   android:layout_width="match_parent" 
   android:layout_height="wrap_content" 
   android:layout_marginTop="55dp" 
   android:text="為什么美國有那么多肌肉極其強大的肌肉男?" 
   android:textSize="18sp" 
   android:background="#DBDBDB" 
   android:gravity="center|left" 
   android:paddingLeft="15dp" 
   android:paddingRight="15dp" 
   android:paddingTop="5dp" 
   android:paddingBottom="5dp" 
   android:textColor="@android:color/darker_gray" 
   /> 
 
  <ImageView 
   android:id="@+id/img_bar" 
   android:layout_width="match_parent" 
   android:layout_height="55dp" 
   android:scaleType="fitXY" 
   android:src="@drawable/bg_actionbar"/> 
 
 </FrameLayout> 
 
 <ImageView 
  android:id="@+id/img_tools" 
  android:layout_width="match_parent" 
  android:layout_height="wrap_content" 
  android:scaleType="fitXY" 
  android:layout_gravity="bottom" 
  android:src="@drawable/bg_bottom"/> 
 
 
</FrameLayout> 

    效果圖如下,文本留了一些空行,保證不被遮擋。

    有的同學(xué)看了上面的效果圖可能會疑惑,這里為什么沒有答題人的布局呢?
    其實是這樣的,為了模擬上部的布局顯示時,Title從Bar下面出現(xiàn)的效果,所以特意這樣設(shè)計的。我試過用linearLayout實現(xiàn),效果也是可以實現(xiàn)的,但是當Title往下移動顯示的時候,會覆蓋在Bar上面,這也很好理解,LinearLayout沒有層次順序,所以會遮擋。我試過View.bringToFront(),試圖把Bar的布局提高層次,但是這樣會導(dǎo)致布局的紊亂,在首次加載的時候,Bar會顯示在最下面,是因為提高層次之后,Bar的布局重新計算,所以不按照LinearLayout的布局規(guī)則來了。無奈之下,換成了Framelayout,但是又出現(xiàn)了問題,Bar的高度可以設(shè)置,但是Title的高度會隨著文本的增加而改變,這樣一來,最下面Author的布局的位置就不能設(shè)置了,因為不知道距離上面多遠,所以我們只能在代碼里面動態(tài)的計算Bar和Title的高度,然后在界面加載的時候,動態(tài)的給Author的布局設(shè)置MargenTop,保證位置的正確。
    因為在onCreate里面,還沒有開始View的繪制,所以得不到控件的真實高度,我們可以用下面的方法,獲取這個時期的高度

//獲取Bar和Title的高度,完成auther布局的margenTop設(shè)置 
  ViewTreeObserver viewTreeObserver = fl_top.getViewTreeObserver(); 
  viewTreeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { 
   @Override 
   public boolean onPreDraw() { 
 
    if (!hasMeasured) { 
     FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout 
       .LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT); 
     layoutParams.setMargins(0, img_bar.getHeight() + tv_title.getHeight(), 0, 0); 
     img_author.setLayoutParams(layoutParams); 
     hasMeasured = true; 
    } 
    return true; 
   } 
  }); 

     獲取了高度之后,我們就可以正確地設(shè)置位置了。但是,如果保證上面的布局隨著我們的內(nèi)容的移動,而改變現(xiàn)實狀態(tài)呢?
    經(jīng)過我手動直觀測試,知乎的這個界面是根據(jù)一個固定的值,來改變顯示狀態(tài)的,因此,我們可以監(jiān)聽ScrollView的滑動距離,來判斷。但是ScrollView并沒有給我們這樣一個監(jiān)聽器,咋辦?重寫!

/** 
 * Created by zhaokaiqiang on 15/2/26. 
 */ 
public class MyScrollView extends ScrollView { 
 
 private BottomListener bottomListener; 
 
 private onScrollListener scrollListener; 
 
 
 public MyScrollView(Context context) { 
  this(context, null); 
 } 
 
 public MyScrollView(Context context, AttributeSet attrs) { 
  super(context, attrs); 
 } 
 
 protected void onScrollChanged(int l, int t, int oldl, int oldt) { 
  super.onScrollChanged(l, t, oldl, oldt); 
  if (getScrollY() + getHeight() >= computeVerticalScrollRange()) { 
 
   if (null != bottomListener) { 
    bottomListener.onBottom(); 
   } 
 
  } 
 
  if (null != scrollListener) { 
   scrollListener.onScrollChanged(l, t, oldl, oldt); 
  } 
 
 
 } 
 
 public void setBottomListener(BottomListener bottomListener) { 
  this.bottomListener = bottomListener; 
 } 
 
 public void setScrollListener(onScrollListener scrollListener) { 
 
  this.scrollListener = scrollListener; 
 
 } 
 
 
 public interface onScrollListener { 
 
  public void onScrollChanged(int l, int t, int oldl, int oldt); 
 
 } 
 
 
 public interface BottomListener { 
 
  public void onBottom(); 
 
 } 
 
 
} 

    我們只需要重寫onScrollChange()方法即可,在里面不光可以時時的得到位置的變化,還添加了一個BottomListener接口來監(jiān)聽滑動到底部的事件,寫好之后就很簡單了

mScroller.setBottomListener(this); 
mScroller.setScrollListener(this); 

/** 
  * 顯示上部的布局 
  */ 
 private void showTop() { 
 
  ObjectAnimator anim1 = ObjectAnimator.ofFloat(img_bar, "y", img_bar.getY(), 
    0); 
  anim1.setDuration(TIME_ANIMATION); 
  anim1.start(); 
 
  ObjectAnimator anim2 = ObjectAnimator.ofFloat(tv_title, "y", tv_title.getY(), 
    img_bar.getHeight()); 
  anim2.setInterpolator(new DecelerateInterpolator()); 
  anim2.setDuration(TIME_ANIMATION + 200); 
  anim2.start(); 
 
  ObjectAnimator anim4 = ObjectAnimator.ofFloat(fl_top, "y", fl_top.getY(), 
    0); 
  anim4.setDuration(TIME_ANIMATION); 
  anim4.start(); 
 
  isTopHide = false; 
 } 
 
 
 /** 
  * 隱藏上部的布局 
  */ 
 private void hideTop() { 
 
  ObjectAnimator anim1 = ObjectAnimator.ofFloat(img_bar, "y", 0, 
    -img_bar.getHeight()); 
  anim1.setDuration(TIME_ANIMATION); 
  anim1.start(); 
 
  ObjectAnimator anim2 = ObjectAnimator.ofFloat(tv_title, "y", tv_title.getY(), 
    -tv_title.getHeight()); 
  anim2.setDuration(TIME_ANIMATION); 
  anim2.start(); 
 
  ObjectAnimator anim4 = ObjectAnimator.ofFloat(fl_top, "y", 0, 
    -(img_bar.getHeight() + tv_title.getHeight())); 
  anim4.setDuration(TIME_ANIMATION); 
  anim4.start(); 
 
  isTopHide = true; 
 } 
 
 @Override 
 public void onBottom() { 
  if (isToolsHide) { 
   showTools(); 
  } 
 } 
 
 @Override 
 public void onScrollChanged(int l, int t, int oldl, int oldt) { 
 
  if (t <= dp2px(TOP_DISTANCE_Y) && isTopHide && isAnimationFinish) { 
   showTop(); 
   Log.d(TAG, "顯示"); 
  } else if (t > dp2px(TOP_DISTANCE_Y) && !isTopHide && isAnimationFinish) { 
   hideTop(); 
   Log.d(TAG, "隱藏"); 
  } 
 } 

    我們只需要根據(jù)當前的位置,來實現(xiàn)布局的顯示和隱藏就可以啦!

    OK,這篇文章就到這里,希望對大家的學(xué)習(xí)有所幫助。

相關(guān)文章

  • Android權(quán)限如何禁止以及友好提示用戶開通必要權(quán)限詳解

    Android權(quán)限如何禁止以及友好提示用戶開通必要權(quán)限詳解

    這篇文章主要給大家介紹了關(guān)于Android權(quán)限如何禁止以及友好提示用戶開通必要權(quán)限的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對各位Android開發(fā)者們具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Android自定義View仿騰訊TIM下拉刷新View

    Android自定義View仿騰訊TIM下拉刷新View

    這篇文章主要給大家介紹了關(guān)于Android自定義View仿騰訊TIM下拉刷新View的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-01-01
  • Android編程實現(xiàn)抽屜效果的方法詳解

    Android編程實現(xiàn)抽屜效果的方法詳解

    這篇文章主要介紹了Android編程實現(xiàn)抽屜效果的方法,結(jié)合具體實例形式分析了Android實現(xiàn)抽屜效果的具體步驟與相關(guān)操作技巧,需要的朋友可以參考下
    2017-05-05
  • Android入門之ListView應(yīng)用解析(二)

    Android入門之ListView應(yīng)用解析(二)

    這篇文章主要介紹了Android入門之ListView應(yīng)用,繼上一篇之后將對Android的ListView用法做更深入的剖析,需要的朋友可以參考下
    2014-08-08
  • Andriod Service與Thread的區(qū)別介紹

    Andriod Service與Thread的區(qū)別介紹

    我們要明確Service是運行在主線程的,不能有耗時操作,這樣,在Service中處理耗時操作的時候,我們依然需要使用線程來處理,既然在Service里也要創(chuàng)建一個子線程,那為什么不直接在Activity里創(chuàng)建呢,下面通過本文給大家介紹Andriod Service與Thread的區(qū)別,一起看看吧
    2017-04-04
  • Android?數(shù)據(jù)結(jié)構(gòu)全面總結(jié)分析

    Android?數(shù)據(jù)結(jié)構(gòu)全面總結(jié)分析

    這篇文章主要為大家介紹了Android?數(shù)據(jù)結(jié)構(gòu)全面總結(jié)分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • Android中EditText光標在4.0中的bug及解決方法

    Android中EditText光標在4.0中的bug及解決方法

    這篇文章主要介紹了Android中EditText光標在4.0中的bug及解決方法,簡單分析了Android4.0版本中EditText光標消息的原因及相應(yīng)的解決方法,需要的朋友可以參考下
    2016-01-01
  • Android文件操作工具類詳解

    Android文件操作工具類詳解

    這篇文章主要為大家詳細介紹了Android文件操作工具類,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • Android錄音并且輸出為Mp4文件的方法教程

    Android錄音并且輸出為Mp4文件的方法教程

    這篇文章主要給大家介紹了關(guān)于Android錄音并且輸出為Mp4文件的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-08-08
  • Android實現(xiàn)標題顯示隱藏功能

    Android實現(xiàn)標題顯示隱藏功能

    這篇文章主要介紹了Android實現(xiàn)標題顯示隱藏功能
    2016-02-02

最新評論