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

Android實(shí)現(xiàn)果凍滑動(dòng)效果的控件

 更新時(shí)間:2016年11月13日 16:48:11   投稿:daisy  
這篇文章給大家主要介紹了利用Android如何實(shí)現(xiàn)果凍效果滑動(dòng)效果的控件,實(shí)現(xiàn)的效果類(lèi)似于iOS有阻尼效果的滑動(dòng)控件,一般我們比較親切地稱(chēng)之為果凍控件,常見(jiàn)的如微信里[我]的那個(gè)面板模塊,即使沒(méi)有再多的選項(xiàng),也不會(huì)很生硬的不允許用戶(hù)滑動(dòng)。下面來(lái)一起看看吧。

前言

在微信是的處理方法是讓用戶(hù)滑動(dòng),但最終還是回滾到最初的地方,這樣的效果很生動(dòng)(畢竟成功還是取決于細(xì)節(jié))。那么在安卓我們要怎么弄呢。下面為大家介紹一下JellyScrollView,是我繼承ScrollView的一個(gè)有阻尼的效果的果凍滑動(dòng)控件。

下面話(huà)不多說(shuō)了,先來(lái)看看效果圖

(在虛擬機(jī)或者真機(jī)跑起來(lái)是很流暢,可能是錄制視頻做成gif的時(shí)候有點(diǎn)卡頓。)

實(shí)現(xiàn)原理

其實(shí)只需要重寫(xiě)下它的攔截方法的邏輯就好了,ScrollView的攔截方法onInterceptTouchEvent一般情況下都默認(rèn)地返回false,表示不攔截該事件。我們只需要在用戶(hù)滑動(dòng)了界面的情況下,攔截下來(lái)并移動(dòng)布局就好了,當(dāng)用戶(hù)松開(kāi)手就恢復(fù)布局。很簡(jiǎn)單

第一步:集成ScrollView重寫(xiě)幾個(gè)構(gòu)造方法;

第二步:重寫(xiě)下onFinishInflate方法,獲得第一個(gè)子view;

第三步:在攔截方法里面處理上面所說(shuō)的邏輯;

public class JellyScrollView extends ScrollView {
 
 private View inner;// 子View
 
 private float y;// 點(diǎn)擊時(shí)y坐標(biāo)
 
 private Rect normal = new Rect();// 矩形(這里只是個(gè)形式,只是用于判斷是否需要?jiǎng)赢?huà).)
 
 private boolean isCount = false;// 是否開(kāi)始計(jì)算
 
 private boolean isMoving = false;// 是否開(kāi)始移動(dòng).
 
 private int top;// 拖動(dòng)時(shí)時(shí)高度。
 
 private int mTouchSlop;//系統(tǒng)最少滑動(dòng)距離
 
 public JellyScrollView(Context context) {
  super(context);
 }
 
 public JellyScrollView(Context context, AttributeSet attrs) {
  super(context, attrs);
 }
 
 public JellyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
 }
 
 /***
 * 根據(jù) XML 生成視圖工作完成.該函數(shù)在生成視圖的最后調(diào)用,在所有子視圖添加完之后. 即使子類(lèi)覆蓋了 onFinishInflate
 * 方法,也應(yīng)該調(diào)用父類(lèi)的方法,使該方法得以執(zhí)行.
 */
 @Override
 protected void onFinishInflate() {
  if (getChildCount() > 0) {
   inner = getChildAt(0);
  }
 }
 
 
 /**攔截事件*/
 @Override
 public boolean onInterceptTouchEvent(MotionEvent ev) {
  if (inner != null) {
   int action = ev.getAction();
   switch (action) {
    case MotionEvent.ACTION_DOWN:
     y = ev.getY();
     top = 0;
     break;
 
    case MotionEvent.ACTION_UP:
     // 手指松開(kāi).
     isMoving = false;
     if (isNeedAnimation()) {
      animation();
     }
     break;
    /***
    * 排除出第一次移動(dòng)計(jì)算,因?yàn)榈谝淮螣o(wú)法得知y坐標(biāo), 在MotionEvent.ACTION_DOWN中獲取不到,
    * 因?yàn)榇藭r(shí)是ScrollView的touch事件傳遞到到了ListView的子item上面.所以從第二次計(jì)算開(kāi)始.
    * 然而我們也要進(jìn)行初始化,就是第一次移動(dòng)的時(shí)候讓滑動(dòng)距離歸0. 之后記錄準(zhǔn)確了就正常執(zhí)行.
    */
    case MotionEvent.ACTION_MOVE:
     final float preY = y;// 按下時(shí)的y坐標(biāo)
     float nowY = ev.getY();// 每時(shí)刻y坐標(biāo)
     int deltaY = (int) (nowY - preY);// 滑動(dòng)距離
     if (!isCount) {
      deltaY = 0; // 在這里要?dú)w0.
     }
 
     if (Math.abs(deltaY) < mTouchSlop && top <= 0)
      return true;
 
     // 當(dāng)滾動(dòng)到最上或者最下時(shí)就不會(huì)再滾動(dòng),這時(shí)移動(dòng)布局
     isNeedMove();
 
     if (isMoving) {
      // 初始化頭部矩形
      if (normal.isEmpty()) {
       // 保存正常的布局位置
       normal.set(inner.getLeft(), inner.getTop(), inner.getRight(), inner.getBottom());
      }
 
      // 移動(dòng)布局
      inner.layout(inner.getLeft(), inner.getTop() + deltaY / 3, inner.getRight(), inner.getBottom() + deltaY / 3);
 
      top += (deltaY / 6);
     }
 
     isCount = true;
     y = nowY;
     break;
   }
  }
  return super.onInterceptTouchEvent(ev);
 }
 
 
 /***
 * 回縮動(dòng)畫(huà)
 */
 public void animation() {
  // 開(kāi)啟移動(dòng)動(dòng)畫(huà)
  TranslateAnimation ta = new TranslateAnimation(0, 0, inner.getTop(), normal.top);
  ta.setDuration(200);
  inner.startAnimation(ta);
 
  // 設(shè)置回到正常的布局位置
  inner.layout(normal.left, normal.top, normal.right, normal.bottom);
  normal.setEmpty();
 
  // 手指松開(kāi)要?dú)w0.
  isCount = false;
  y = 0;
 }
 
 // 是否需要開(kāi)啟動(dòng)畫(huà)
 public boolean isNeedAnimation() {
  return !normal.isEmpty();
 }
 
 /***
 * 是否需要移動(dòng)布局
 * inner.getMeasuredHeight():獲取的是控件的總高度
 * getHeight():獲取的是屏幕的高度
 *
 * @return
 */
 public void isNeedMove() {
  int offset = inner.getMeasuredHeight() - getHeight();
  int scrollY = getScrollY();
  // scrollY == 0是頂部
  // scrollY == offset是底部
if (scrollY == 0 || scrollY == offset) {
 isMoving = true;
}
 }
}

然后在布局里面在最外層就使用我們的JellyScrollView

(為了方便展示,我只是大概寫(xiě)了一部分布局代碼)

<?xml version="1.0" encoding="utf-8"?><cn.ichengxi.fang.view.JellyScrollView xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="@color/bg"
 android:scrollbars="none">
 
 <LinearLayout  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:orientation="vertical">
  <TextView   android:id="@+id/personal_setting_txt"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:alpha="0.8"
   android:gravity="center_vertical"
   android:text="設(shè)置"
   android:textColor="@android:color/black" />
 
 </LinearLayout></cn.ichengxi.fang.view.JellyScrollView>12345678910111213141516171819202122231234567891011121314151617181920212223

總結(jié)

好了,這樣就可以很優(yōu)雅的實(shí)現(xiàn)了果凍控件的效果啦。以上就是本文的全部?jī)?nèi)容了,希望這篇文章的內(nèi)容對(duì)大家能有所幫助,如果有疑問(wèn)大家可以留言交流。

相關(guān)文章

最新評(píng)論