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

ViewDragHelper實(shí)現(xiàn)QQ側(cè)滑效果

 更新時(shí)間:2017年08月29日 10:08:59   作者:Kiven_Android  
這篇文章主要為大家詳細(xì)介紹了ViewDragHelper實(shí)現(xiàn)QQ側(cè)滑效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

前言

       側(cè)滑的實(shí)現(xiàn)方式有很多方式來(lái)實(shí)現(xiàn),這次總結(jié)的ViewDragHelper就是其中一種方式,ViewDragHelper是2013年谷歌I/O大會(huì)發(fā)布的新的控件,為了解決界面控件拖拽問(wèn)題。下面就是自己學(xué)習(xí)寫的一個(gè)實(shí)現(xiàn)類似于QQ側(cè)滑效果的實(shí)現(xiàn)。
activity_main.xml:

<com.yctc.drag.DragLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/dl"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="@drawable/bg"
 tools:context=".MainActivity" >

 <LinearLayout
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical"
  android:paddingBottom="50dp"
  android:paddingLeft="10dp"
  android:paddingRight="50dp"
  android:paddingTop="50dp" >

  <ImageView
   android:layout_width="50dp"
   android:layout_height="50dp"
   android:src="@drawable/head" />

  <ListView
   android:id="@+id/lv_left"
   android:layout_width="match_parent"
   android:layout_height="match_parent" >
  </ListView>
 </LinearLayout>

 <com.yctc.drag.MyLinearLayout
  android:id="@+id/mll"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="#ffffff"
  android:orientation="vertical" >

  <RelativeLayout
   android:layout_width="match_parent"
   android:layout_height="50dp"
   android:background="#18B6EF"
   android:gravity="center_vertical" >

   <ImageView
    android:id="@+id/iv_header"
    android:layout_width="30dp"
    android:layout_height="30dp"
    android:layout_marginLeft="15dp"
    android:src="@drawable/head" />

   <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:text="Header" />
  </RelativeLayout>

  <ListView
   android:id="@+id/lv_main"
   android:layout_width="match_parent"
   android:layout_height="match_parent" >
  </ListView>
 </com.yctc.drag.MyLinearLayout>
</com.yctc.drag.DragLayout>


DragLayout.Java:

public class DragLayout extends FrameLayout {

 private static final String TAG = "TAG";
 private ViewDragHelper mDragHelper;
 private ViewGroup mLeftContent;
 private ViewGroup mMainContent;
 private OnDragStatusChangeListener mListener;
 private Status mStatus = Status.Close;

 /**
  * 狀態(tài)枚舉
  */
 public static enum Status {
  Close, Open, Draging;
 }
 public interface OnDragStatusChangeListener{
  void onClose();
  void onOpen();
  void onDraging(float percent);
 }

 public Status getStatus() {
  return mStatus;
 }

 public void setStatus(Status mStatus) {
  this.mStatus = mStatus;
 }

 public void setDragStatusListener(OnDragStatusChangeListener mListener){
  this.mListener = mListener;
 }

 public DragLayout(Context context) {
  this(context, null);
 }

 public DragLayout(Context context, AttributeSet attrs) {
  this(context, attrs, 0);
 }

 public DragLayout(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);

  // a.初始化 (通過(guò)靜態(tài)方法) 
  mDragHelper = ViewDragHelper.create(this , mCallback);

 }

 ViewDragHelper.Callback mCallback = new ViewDragHelper.Callback() {
  // c. 重寫事件

  // 1. 根據(jù)返回結(jié)果決定當(dāng)前child是否可以拖拽
  // child 當(dāng)前被拖拽的View
  // pointerId 區(qū)分多點(diǎn)觸摸的id
  @Override
  public boolean tryCaptureView(View child, int pointerId) {
   Log.d(TAG, "tryCaptureView: " + child);
   return true;
  };

  @Override
  public void onViewCaptured(View capturedChild, int activePointerId) {
   Log.d(TAG, "onViewCaptured: " + capturedChild);
   // 當(dāng)capturedChild被捕獲時(shí),調(diào)用.
   super.onViewCaptured(capturedChild, activePointerId);
  }

  @Override
  public int getViewHorizontalDragRange(View child) {
   // 返回拖拽的范圍, 不對(duì)拖拽進(jìn)行真正的限制. 僅僅決定了動(dòng)畫執(zhí)行速度
   return mRange;
  }

  // 2. 根據(jù)建議值 修正將要移動(dòng)到的(橫向)位置 (重要)
  // 此時(shí)沒(méi)有發(fā)生真正的移動(dòng)
  public int clampViewPositionHorizontal(View child, int left, int dx) {
   // child: 當(dāng)前拖拽的View
   // left 新的位置的建議值, dx 位置變化量
   // left = oldLeft + dx;
   Log.d(TAG, "clampViewPositionHorizontal: " 
     + "oldLeft: " + child.getLeft() + " dx: " + dx + " left: " +left);

   if(child == mMainContent){
    left = fixLeft(left);
   }
   return left;
  }

  // 3. 當(dāng)View位置改變的時(shí)候, 處理要做的事情 (更新?tīng)顟B(tài), 伴隨動(dòng)畫, 重繪界面)
  // 此時(shí),View已經(jīng)發(fā)生了位置的改變
  @Override
  public void onViewPositionChanged(View changedView, int left, int top,
    int dx, int dy) {
   // changedView 改變位置的View
   // left 新的左邊值
   // dx 水平方向變化量
   super.onViewPositionChanged(changedView, left, top, dx, dy);
   Log.d(TAG, "onViewPositionChanged: " + "left: " + left + " dx: " + dx);

   int newLeft = left;
   if(changedView == mLeftContent){
    // 把當(dāng)前變化量傳遞給mMainContent
    newLeft = mMainContent.getLeft() + dx;
   }

   // 進(jìn)行修正
   newLeft = fixLeft(newLeft);

   if(changedView == mLeftContent) {
    // 當(dāng)左面板移動(dòng)之后, 再?gòu)?qiáng)制放回去.
    mLeftContent.layout(0, 0, 0 + mWidth, 0 + mHeight);
    mMainContent.layout(newLeft, 0, newLeft + mWidth, 0 + mHeight);
   }
   // 更新?tīng)顟B(tài),執(zhí)行動(dòng)畫
   dispatchDragEvent(newLeft);

   // 為了兼容低版本, 每次修改值之后, 進(jìn)行重繪
   invalidate();
  }

  // 4. 當(dāng)View被釋放的時(shí)候, 處理的事情(執(zhí)行動(dòng)畫)
  @Override
  public void onViewReleased(View releasedChild, float xvel, float yvel) {
   // View releasedChild 被釋放的子View 
   // float xvel 水平方向的速度, 向右為+
   // float yvel 豎直方向的速度, 向下為+
   Log.d(TAG, "onViewReleased: " + "xvel: " + xvel + " yvel: " + yvel);
   super.onViewReleased(releasedChild, xvel, yvel);

   // 判斷執(zhí)行 關(guān)閉/開(kāi)啟
   // 先考慮所有開(kāi)啟的情況,剩下的就都是關(guān)閉的情況
   if(xvel == 0 && mMainContent.getLeft() > mRange / 2.0f){
    open();
   }else if (xvel > 0) {
    open();
   }else {
    close();
   }

  }

  @Override
  public void onViewDragStateChanged(int state) {
   // TODO Auto-generated method stub
   super.onViewDragStateChanged(state);
  }

 };

 /**
  * 根據(jù)范圍修正左邊值
  * @param left
  * @return
  */
 private int fixLeft(int left) {
  if(left < 0){
   return 0;
  }else if (left > mRange) {
   return mRange;
  }
  return left;
 }

 protected void dispatchDragEvent(int newLeft) {
  float percent = newLeft * 1.0f/ mRange;
  //0.0f -> 1.0f
  Log.d(TAG, "percent: " + percent);

  if(mListener != null){
   mListener.onDraging(percent);
  }

  // 更新?tīng)顟B(tài), 執(zhí)行回調(diào)
  Status preStatus = mStatus;
  mStatus = updateStatus(percent);
  if(mStatus != preStatus){
   // 狀態(tài)發(fā)生變化
   if(mStatus == Status.Close){
    // 當(dāng)前變?yōu)殛P(guān)閉狀態(tài)
    if(mListener != null){
     mListener.onClose();
    }
   }else if (mStatus == Status.Open) {
    if(mListener != null){
     mListener.onOpen();
    }
   }
  }

//  * 伴隨動(dòng)畫:
  animViews(percent);

 }

 private Status updateStatus(float percent) {
  if(percent == 0f){
   return Status.Close;
  }else if (percent == 1.0f) {
   return Status.Open;
  }
  return Status.Draging;
 }

 private void animViews(float percent) {
  //  > 1. 左面板: 縮放動(dòng)畫, 平移動(dòng)畫, 透明度動(dòng)畫
     // 縮放動(dòng)畫 0.0 -> 1.0 >>> 0.5f -> 1.0f >>> 0.5f * percent + 0.5f
   //  mLeftContent.setScaleX(0.5f + 0.5f * percent);
   //  mLeftContent.setScaleY(0.5f + 0.5f * percent);
     ViewHelper.setScaleX(mLeftContent, evaluate(percent, 0.5f, 1.0f));
     ViewHelper.setScaleY(mLeftContent, 0.5f + 0.5f * percent);
     // 平移動(dòng)畫: -mWidth / 2.0f -> 0.0f
     ViewHelper.setTranslationX(mLeftContent, evaluate(percent, -mWidth / 2.0f, 0));
     // 透明度: 0.5 -> 1.0f
     ViewHelper.setAlpha(mLeftContent, evaluate(percent, 0.5f, 1.0f));

  //  > 2. 主面板: 縮放動(dòng)畫
     // 1.0f -> 0.8f
     ViewHelper.setScaleX(mMainContent, evaluate(percent, 1.0f, 0.8f));
     ViewHelper.setScaleY(mMainContent, evaluate(percent, 1.0f, 0.8f));

  //  > 3. 背景動(dòng)畫: 亮度變化 (顏色變化)
     getBackground().setColorFilter((Integer)evaluateColor(percent, Color.BLACK, Color.TRANSPARENT), Mode.SRC_OVER);
 }

 /**
  * 估值器
  * @param fraction
  * @param startValue
  * @param endValue
  * @return
  */
 public Float evaluate(float fraction, Number startValue, Number endValue) {
  float startFloat = startValue.floatValue();
  return startFloat + fraction * (endValue.floatValue() - startFloat);
 }
 /**
  * 顏色變化過(guò)度
  * @param fraction
  * @param startValue
  * @param endValue
  * @return
  */
 public Object evaluateColor(float fraction, Object startValue, Object endValue) {
  int startInt = (Integer) startValue;
  int startA = (startInt >> 24) & 0xff;
  int startR = (startInt >> 16) & 0xff;
  int startG = (startInt >> 8) & 0xff;
  int startB = startInt & 0xff;

  int endInt = (Integer) endValue;
  int endA = (endInt >> 24) & 0xff;
  int endR = (endInt >> 16) & 0xff;
  int endG = (endInt >> 8) & 0xff;
  int endB = endInt & 0xff;

  return (int)((startA + (int)(fraction * (endA - startA))) << 24) |
    (int)((startR + (int)(fraction * (endR - startR))) << 16) |
    (int)((startG + (int)(fraction * (endG - startG))) << 8) |
    (int)((startB + (int)(fraction * (endB - startB))));
 }

 @Override
 public void computeScroll() {
  super.computeScroll();

  // 2. 持續(xù)平滑動(dòng)畫 (高頻率調(diào)用)
  if(mDragHelper.continueSettling(true)){
   // 如果返回true, 動(dòng)畫還需要繼續(xù)執(zhí)行
   ViewCompat.postInvalidateOnAnimation(this);
  }
 }

 public void close(){
  close(true);
 }
 /**
  * 關(guān)閉
  */
 public void close(boolean isSmooth) {
  int finalLeft = 0;
  if(isSmooth){
   // 1. 觸發(fā)一個(gè)平滑動(dòng)畫
   if(mDragHelper.smoothSlideViewTo(mMainContent, finalLeft, 0)){
    // 返回true代表還沒(méi)有移動(dòng)到指定位置, 需要刷新界面.
    // 參數(shù)傳this(child所在的ViewGroup)
    ViewCompat.postInvalidateOnAnimation(this);
   }
  }else {
   mMainContent.layout(finalLeft, 0, finalLeft + mWidth, 0 + mHeight);
  }
 }

 public void open(){
  open(true);
 }
 /**
  * 開(kāi)啟
  */
 public void open(boolean isSmooth) {
  int finalLeft = mRange;
  if(isSmooth){
   // 1. 觸發(fā)一個(gè)平滑動(dòng)畫
   if(mDragHelper.smoothSlideViewTo(mMainContent, finalLeft, 0)){
    // 返回true代表還沒(méi)有移動(dòng)到指定位置, 需要刷新界面.
    // 參數(shù)傳this(child所在的ViewGroup)
    ViewCompat.postInvalidateOnAnimation(this);
   }
  }else {
   mMainContent.layout(finalLeft, 0, finalLeft + mWidth, 0 + mHeight);
  }
 }

 private int mHeight;
 private int mWidth;
 private int mRange;

 // b.傳遞觸摸事件
 @Override
 public boolean onInterceptTouchEvent(MotionEvent ev) {
  // 傳遞給mDragHelper
  return mDragHelper.shouldInterceptTouchEvent(ev);
 }
 @Override
 public boolean onTouchEvent(MotionEvent event) {
  try {
   mDragHelper.processTouchEvent(event);
  } catch (Exception e) {
   e.printStackTrace();
  }
  // 返回true, 持續(xù)接受事件
  return true;
 }

 @Override
 protected void onFinishInflate() {
  super.onFinishInflate();
  // Github
  // 寫注釋
  // 容錯(cuò)性檢查 (至少有倆子View, 子View必須是ViewGroup的子類)

  if(getChildCount() < 2){
   throw new IllegalStateException("布局至少有倆孩子. Your ViewGroup must have 2 children at least.");
  }
  if(!(getChildAt(0) instanceof ViewGroup && getChildAt(1) instanceof ViewGroup)){
   throw new IllegalArgumentException("子View必須是ViewGroup的子類. Your children must be an instance of ViewGroup");
  }

  mLeftContent = (ViewGroup) getChildAt(0);
  mMainContent = (ViewGroup) getChildAt(1);
 }

 @Override
 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  super.onSizeChanged(w, h, oldw, oldh);
  // 當(dāng)尺寸有變化的時(shí)候調(diào)用

  mHeight = getMeasuredHeight();
  mWidth = getMeasuredWidth();

  // 移動(dòng)的范圍
  mRange = (int) (mWidth * 0.6f);

 }

}

MyLineatLayout.java:

public class MyLinearLayout extends LinearLayout {

 private DragLayout mDragLayout;

 public MyLinearLayout(Context context) {
  super(context);
 }

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

 public void setDraglayout(DragLayout mDragLayout){
  this.mDragLayout = mDragLayout;
 }

 @Override
 public boolean onInterceptTouchEvent(MotionEvent ev) {
  // 如果當(dāng)前是關(guān)閉狀態(tài), 按之前方法判斷
  if(mDragLayout.getStatus() == Status.Close){
   return super.onInterceptTouchEvent(ev);
  }else {
   return true;
  }
 }

 @Override
 public boolean onTouchEvent(MotionEvent event) {
  // 如果當(dāng)前是關(guān)閉狀態(tài), 按之前方法處理
  if(mDragLayout.getStatus() == Status.Close){
   return super.onTouchEvent(event);
  }else {
   // 手指抬起, 執(zhí)行關(guān)閉操作
   if(event.getAction() == MotionEvent.ACTION_UP){
    mDragLayout.close();
   }

   return true;
  }
 }

}

MainActivity.java:

public class MainActivity extends Activity {

 private static final String TAG = "TAG";

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  requestWindowFeature(Window.FEATURE_NO_TITLE);
  setContentView(R.layout.activity_main);

  final ListView mLeftList = (ListView) findViewById(R.id.lv_left);
  final ListView mMainList = (ListView) findViewById(R.id.lv_main);
  final ImageView mHeaderImage = (ImageView) findViewById(R.id.iv_header);
  MyLinearLayout mLinearLayout = (MyLinearLayout) findViewById(R.id.mll);

  // 查找Draglayout, 設(shè)置監(jiān)聽(tīng)
  DragLayout mDragLayout = (DragLayout) findViewById(R.id.dl);

  // 設(shè)置引用
  mLinearLayout.setDraglayout(mDragLayout);

  mDragLayout.setDragStatusListener(new OnDragStatusChangeListener() {

   @Override
   public void onOpen() {
    Utils.showToast(MainActivity.this, "onOpen");
    // 左面板ListView隨機(jī)設(shè)置一個(gè)條目
    Random random = new Random();

    int nextInt = random.nextInt(50);
    mLeftList.smoothScrollToPosition(nextInt);

   }

   @Override
   public void onDraging(float percent) {
    Log.d(TAG, "onDraging: " + percent);// 0 -> 1
    // 更新圖標(biāo)的透明度
    // 1.0 -> 0.0
    ViewHelper.setAlpha(mHeaderImage, 1 - percent);
   }

   @Override
   public void onClose() {
    Utils.showToast(MainActivity.this, "onClose");
    // 讓圖標(biāo)晃動(dòng)
//    mHeaderImage.setTranslationX(translationX)
    ObjectAnimator mAnim = ObjectAnimator.ofFloat(mHeaderImage, "translationX", 15.0f);
    mAnim.setInterpolator(new CycleInterpolator(4));
    mAnim.setDuration(500);
    mAnim.start();
   }
  });

  mLeftList.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, Cheeses.sCheeseStrings){
   @Override
   public View getView(int position, View convertView, ViewGroup parent) {
    View view = super.getView(position, convertView, parent);
    TextView mText = ((TextView)view);
    mText.setTextColor(Color.WHITE);
    return view;
   }
  });

  mMainList.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, Cheeses.NAMES))  
 }
}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android中Serializable和Parcelable序列化對(duì)象詳解

    Android中Serializable和Parcelable序列化對(duì)象詳解

    這篇文章主要介紹了Android中Serializable和Parcelable序列化對(duì)象的相關(guān)資料,感興趣的小伙伴們可以參考一下
    2016-02-02
  • Android實(shí)現(xiàn)輕量線性與百分比圖表的方法

    Android實(shí)現(xiàn)輕量線性與百分比圖表的方法

    這篇文章主要給大家介紹了關(guān)于Android實(shí)現(xiàn)輕量線性與百分比圖表的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)學(xué)習(xí)吧。
    2017-12-12
  • Android仿微信主界面的實(shí)現(xiàn)方法

    Android仿微信主界面的實(shí)現(xiàn)方法

    這篇文章主要為大家詳細(xì)介紹了Android仿微信主界面的實(shí)現(xiàn)方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • Android 屏幕切換監(jiān)聽(tīng)的實(shí)例代碼

    Android 屏幕切換監(jiān)聽(tīng)的實(shí)例代碼

    我試著在屏幕切換時(shí),使View顯示在不同的位置,在網(wǎng)上搜索了一些資料,自己做了一段時(shí)間,終于完成了功能,今天小編給大家分享android 屏幕切換監(jiān)聽(tīng)的實(shí)例代碼,需要的的朋友參考下吧
    2017-01-01
  • Android自定義Animation實(shí)現(xiàn)View搖擺效果

    Android自定義Animation實(shí)現(xiàn)View搖擺效果

    這篇文章主要為大家詳細(xì)介紹了Android自定義Animation實(shí)現(xiàn)View搖擺效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • Android Fragment中使用SurfaceView切換時(shí)閃一下黑屏的解決辦法

    Android Fragment中使用SurfaceView切換時(shí)閃一下黑屏的解決辦法

    本篇文章主要給大家分享Android Fragment中使用SurfaceView切換時(shí)閃一下黑屏的解決辦法,需要的朋友可以參考下
    2015-09-09
  • Android 混合動(dòng)畫詳解及實(shí)現(xiàn)代碼

    Android 混合動(dòng)畫詳解及實(shí)現(xiàn)代碼

    這篇文章主要介紹了Android 混合動(dòng)畫詳解及實(shí)現(xiàn)代碼的相關(guān)資料,簡(jiǎn)單的一種動(dòng)畫(如旋轉(zhuǎn)、縮放、漸變、位移等)有時(shí)候并不能滿足我們項(xiàng)目的要求,這時(shí)候就需要運(yùn)用到混合動(dòng)畫,需要的朋友可以參考下
    2016-11-11
  • Android實(shí)現(xiàn)一個(gè)比相冊(cè)更高大上的左右滑動(dòng)特效(附源碼)

    Android實(shí)現(xiàn)一個(gè)比相冊(cè)更高大上的左右滑動(dòng)特效(附源碼)

    這篇文章主要介紹了Android實(shí)現(xiàn)一個(gè)比相冊(cè)更高大上的左右滑動(dòng)特效(附源碼),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02
  • Android?Java?crash?處理流程詳解

    Android?Java?crash?處理流程詳解

    這篇文章主要為大家介紹了Android?Java?crash?處理流程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • Android實(shí)現(xiàn)幾種推送方式解決方案

    Android實(shí)現(xiàn)幾種推送方式解決方案

    推送功能在手機(jī)開(kāi)發(fā)中應(yīng)用的場(chǎng)景是越來(lái)起來(lái)了,本篇文章主要介紹了Android實(shí)現(xiàn)幾種推送方式解決方案 ,具有一定的參考價(jià)值,有興趣的可以了解一下。
    2016-12-12

最新評(píng)論