側滑2

来源:http://www.cnblogs.com/wangfengdange/archive/2016/02/16/5192071.html
-Advertisement-
Play Games

如下圖是側滑的效果圖 實現的功能主要是用ViewDragHelper,用ViewDragHelper來自定義一個側滑面板來實現側滑 如下是自定義的側滑面板 1 package com.demo.sb.widget; 2 3 import com.nineoldandroids.view.ViewHe


如下圖是側滑的效果圖

                             

 

實現的功能主要是用ViewDragHelper,用ViewDragHelper來自定義一個側滑面板來實現側滑

如下是自定義的側滑面板

  1 package com.demo.sb.widget;
  2 
  3 import com.nineoldandroids.view.ViewHelper;
  4 
  5 import android.content.Context;
  6 import android.graphics.Color;
  7 import android.graphics.PorterDuff.Mode;
  8 import android.support.v4.view.ViewCompat;
  9 import android.support.v4.widget.ViewDragHelper;
 10 import android.util.AttributeSet;
 11 import android.util.Log;
 12 import android.view.MotionEvent;
 13 import android.view.View;
 14 import android.view.ViewGroup;
 15 import android.widget.FrameLayout;
 16 
 17 /**
 18  * 側滑面板
 19  * 
 20  * @author Administrator
 21  * 
 22  */
 23 public class DragLayout extends FrameLayout {
 24 
 25     private ViewDragHelper mDragHelper;
 26     private ViewGroup mLeftContent;
 27     private ViewGroup mMainContent;
 28 
 29     private Status mStatus = Status.Close;
 30     private OnDragStatusChangeListener mListener;
 31 
 32     /**
 33      * 狀態枚舉
 34      */
 35     public static enum Status {
 36         Close, Open, Draging;
 37     }
 38 
 39     public interface OnDragStatusChangeListener {
 40         void onClose();
 41 
 42         void onOpen();
 43 
 44         void onDraging(float percent);
 45     }
 46 
 47     public Status getStatus() {
 48         return mStatus;
 49     }
 50 
 51     public void setStatus(Status mStatus) {
 52         this.mStatus = mStatus;
 53     }
 54 
 55     public void setDragStatusListener(OnDragStatusChangeListener mListener) {
 56         this.mListener = mListener;
 57     }
 58 
 59     public DragLayout(Context context) {
 60         this(context, null);
 61         // TODO Auto-generated constructor stub
 62     }
 63 
 64     public DragLayout(Context context, AttributeSet attrs) {
 65         this(context, attrs, 0);
 66         // TODO Auto-generated constructor stub
 67     }
 68 
 69     public DragLayout(Context context, AttributeSet attrs, int defStyle) {
 70         super(context, attrs, defStyle);
 71         // TODO Auto-generated constructor stub
 72         /**
 73          * a . 初始化(通過靜態的方法)
 74          */
 75         mDragHelper = ViewDragHelper.create(this, mCallback);
 76     }
 77 
 78     /**
 79      * c. 重寫Callback的事件
 80      */
 81     ViewDragHelper.Callback mCallback = new ViewDragHelper.Callback() {
 82         /**
 83          * 1. 根據返回結果決定當前的child是否可以拖拽 child 當前被拖拽的View pointerId 區分多點觸摸的id
 84          */
 85         @Override
 86         public boolean tryCaptureView(View child, int pointerId) {
 87             Log.d("jiejie", "tryCaptureView: " + child);
 88             return true;// 都可以嘗試被拖拽
 89             // return child == mMainContent;//只有主程式的View可以被拖拽
 90         }
 91 
 92         public void onViewCaptured(View capturedChild, int activePointerId) {
 93             // 當capturedChild被捕獲時,調用
 94             Log.d("jiejie", "onViewCaptured: " + capturedChild);
 95         }
 96 
 97         public int getViewHorizontalDragRange(View child) {
 98             // 返回拖拽的範圍,不對拖拽進行真正的限制。僅僅決定了動畫的執行速度
 99             return mRange;
100         }
101 
102         /**
103          * 2. 根據建議值 修正將要移動到的(橫向)位置(重要) 此時還沒有真正移動
104          */
105         public int clampViewPositionHorizontal(View child, int left, int dx) {
106             Log.d("jiejie", "clampViewPositionHorizontal: " + left);
107             if (child == mMainContent) {
108                 left = fixLeft(left);
109             }
110             return left;
111         }
112 
113         /**
114          * 3. 當View位置改變的時候,處理要做的事情(更新狀態, 伴隨動畫, 重繪界面) 此時,View已經發生了位置的改變
115          * changedView 改變位置的View left 新的左邊值 dx 水平方向變化量
116          */
117         public void onViewPositionChanged(View changedView, int left, int top,
118                 int dx, int dy) {
119             super.onViewPositionChanged(changedView, left, top, dx, dy);
120             Log.d("jiejie", "onViewPositionChanged: " + "left:" + left
121                     + " dx: " + dx);
122             int newLeft = left;
123             if (changedView == mLeftContent) {
124                 // 把當前變化量專遞給mMainContent
125                 newLeft = mMainContent.getLeft() + dx;
126             }
127             // 進行修正
128             newLeft = fixLeft(newLeft);
129 
130             if (changedView == mLeftContent) {
131                 // 當左面板移動之後,再強制放回去
132                 mLeftContent.layout(0, 0, 0 + mWidth, 0 + mHeight);
133                 mMainContent.layout(newLeft, 0, newLeft + mWidth, 0 + mHeight);
134             }
135 
136             /**
137              * 更新狀態時設置動畫(也可以不設置,不設置的話則預設平滑的狀態,也可以省很多代碼) 設置左面板和主面板,背景的動畫
138              */
139             dispatchDragEvent(newLeft);
140 
141             // 為了相容低版本,每次修改值之後,進行重繪
142             invalidate();
143         }
144 
145         /**
146          * 4. 當View被釋放的時候,處理的事情(執行動畫) View releasedChild 被釋放的子View float xvel
147          * 水平方向的速度,向右為正 float yvel 豎直方向的速度, 向下為正
148          */
149         public void onViewReleased(View releasedChild, float xvel, float yvel) {
150             Log.d("jiejie", "onViewReleased: " + "xvel: " + xvel + "yvel: "
151                     + yvel);
152             super.onViewReleased(releasedChild, xvel, yvel);
153             // 判斷執行 關閉/開啟
154             // 先考慮所有開啟的情況,剩下的就是都是關閉的情況
155             if (xvel == 0 && mMainContent.getLeft() > (mRange / 2.0f)) {
156                 open();
157             } else if (xvel > 0) {
158                 open();
159             } else {
160                 chose();
161             }
162         }
163 
164         public void onViewDragStateChanged(int state) {
165             super.onViewDragStateChanged(state);
166         }
167     };
168 
169     /**
170      * 根據範圍修正左邊值
171      * 
172      * @param left
173      * @return
174      */
175     private int fixLeft(int left) {
176         if (left < 0) {
177             return 0;
178         } else if (left > mRange) {
179             return mRange;
180         }
181         return left;
182     }
183 
184     /**
185      * 執行動畫
186      * 
187      * @param newLeft
188      */
189     protected void dispatchDragEvent(int newLeft) {
190         // TODO Auto-generated method stub
191         float percent = newLeft * 1.0f / mRange;
192         Log.d("jiejie", "percent: " + percent);
193         if (mListener != null) {
194             mListener.onDraging(percent);
195         }
196 
197         // 更新狀態,執行回調
198         Status preStatus = mStatus;
199         mStatus = updateStatus(percent);
200 
201         if (mStatus != preStatus) {
202             // 狀態發生變化
203             if (mStatus == Status.Close) {
204                 // 當前變為關閉狀態
205                 if (mListener != null) {
206                     mListener.onClose();
207                 }
208             } else if (mStatus == Status.Open) {
209                 if (mListener != null) {
210                     mListener.onOpen();
211                 }
212             }
213         }
214 
215         // 伴隨動畫
216         animViews(percent);
217     }
218 
219     private Status updateStatus(float percent) {
220         if (percent == 0f) {
221             return Status.Close;
222         } else if (percent == 1.0f) {
223             return Status.Open;
224         }
225         return Status.Draging;
226     }
227 
228     private void animViews(float percent) {
229         // TODO Auto-generated method stub
230         /**
231          * >1.左面板:縮放動畫,平移動畫,透明度動畫 縮放動畫0.0 - > 1.0 >> 0.5f -> 1.0f >>>
232          * 0.5f*percent+0.5f mLeftContent.setScaleX(0.5f + 0.5f * percent);
233          * mLeftContent.setScaleY(0.5f + 0.5f * percent);
234          */
235         // mLeftContent.setScaleY(0.5f + 0.5f * percent);
236         // mLeftContent.setScaleX(0.5f + 0.5f * percent);
237         ViewHelper.setScaleX(mLeftContent, evaluate(percent, 0.5f, 1.0f));
238         ViewHelper.setScaleY(mLeftContent, 0.5f + 0.5f * percent);
239         // 平移動畫:-mWidth / 2.0 f - > 0.0f
240         ViewHelper.setTranslationX(mLeftContent,
241                 evaluate(percent, -mWidth / 2.0f, 0));
242         // 透明度: 0.5 -> 1.0f
243         ViewHelper.setAlpha(mLeftContent, evaluate(percent, 0.5f, 1.0f));
244 
245         /**
246          * >2. 主面板:縮放動畫
247          */
248         // 1.0f -> 0.8f
249         ViewHelper.setScaleX(mMainContent, evaluate(percent, 1.0f, 0.8f));
250         ViewHelper.setScaleY(mMainContent, evaluate(percent, 1.0f, 0.8f));
251 
252         /**
253          * >3. 背景動畫: 亮度變化(顏色變化)
254          */
255         getBackground()
256                 .setColorFilter(
257                         (Integer) evaluateColor(percent, Color.BLACK,
258                                 Color.TRANSPARENT), Mode.SRC_OVER);
259     }
260 
261     /**
262      * 估值器
263      * 
264      * @param fraction
265      * @param startValue
266      * @param endValue
267      * @return
268      */
269     public Float evaluate(float fraction, Number startValue, Number endValue) {
270         float startFloat = startValue.floatValue();
271         return startFloat + fraction * (endValue.floatValue() - startFloat);
272     }
273 
274     /**
275      * 顏色變化過度
276      * 
277      * @param fraction
278      * @param startValue
279      * @param endValue
280      * @return
281      */
282     public Object evaluateColor(float fraction, Object startValue,
283             Object endValue) {
284         int startInt = (Integer) startValue;
285         int startA = (startInt >> 24) & 0xff;
286         int startR = (startInt >> 16) & 0xff;
287         int startG = (startInt >> 8) & 0xff;
288         int startB = startInt & 0xff;
289 
290         int endInt = (Integer) endValue;
291         int endA = (endInt >> 24) & 0xff;
292         int endR = (endInt >> 16) & 0xff;
293         int endG = (endInt >> 8) & 0xff;
294         int endB = endInt & 0xff;
295 
296         return (int) ((startA + (int) (fraction * (endA - startA))) << 24)
297                 | (int) ((startR + (int) (fraction * (endR - startR))) << 16)
298                 | (int) ((startG + (int) (fraction * (endG - startG))) << 8)
299                 | (int) ((startB + (int) (fraction * (endB - startB))));
300     }
301 
302     @Override
303     public void computeScroll() {
304         // TODO Auto-generated method stub
305         super.computeScroll();
306         // 2. 持續平滑動畫(高頻率調用)
307         if (mDragHelper.continueSettling(true)) {
308             // 如果返回true,動畫還需要繼續執行
309             ViewCompat.postInvalidateOnAnimation(this);
310         }
311     }
312 
313     // public void chose() {
314     // // TODO Auto-generated method stub
315     // chose(true);
316     // }
317     public void chose() {
318         // TODO Auto-generated method stub
319         chose(true);
320     }
321 
322     /**
323      * 關閉
324      * 
325      * @param b
326      */
327     public void chose(boolean isSmooth) {
328         // TODO Auto-generated method stub
329         int finalLeft = 0;
330         // 1. 觸發一個平滑動畫
331         if (isSmooth) {
332             if (mDragHelper.smoothSlideViewTo(mMainContent, finalLeft, 0)) {
333                 // 返回true代表還沒有移動到指定位置,需要刷新界面
334                 // 參數傳this(child所在的ViewGroup)
335                 ViewCompat.postInvalidateOnAnimation(this);
336             }
337         } else {
338             mMainContent.layout(finalLeft, 0, finalLeft + mWidth, 0 + mHeight);
339         }
340     }
341 
342     public void open() {
343         // TODO Auto-generated method stub
344         open(true);
345     }
346 
347     /**
348      * 開啟
349      * 
350      * @param b
351      */
352     public void open(boolean isSmooth) {
353         // TODO Auto-generated method stub
354         int finalLeft = mRange;
355         if (isSmooth) {
356             // 1. 觸發一個平滑動畫
357             if (mDragHelper.smoothSlideViewTo(mMainContent, finalLeft, 0)) {
358                 // 返回true代表還沒有移動到指定位置,需要刷新界面
359                 // 參數this(child所在的ViewGroup)
360                 ViewCompat.postInvalidateOnAnimation(this);
361             }
362         } else {
363             mMainContent.layout(finalLeft, 0, finalLeft + mWidth, 0 + mHeight);
364         }
365     }
366 
367     /**
368      * b. 專遞觸摸事件
369      */
370     public boolean onInterceptTouchEvent(MotionEvent ev) {
371         // 傳遞給mDragHandler
372         return mDragHelper.shouldInterceptTouchEvent(ev);
373     };
374 
375     @Override
376     public boolean onTouchEvent(MotionEvent event) {
377         // TODO Auto-generated method stub
378         try {
379             mDragHelper.processTouchEvent(event);
380         } catch (Exception e) {
381             e.printStackTrace();
382         }
383         // 返回true,持續接收事件
384         return true;
385     }
386 
387     /**
388      * 當View中所有的子控制項 均被映射成xml後觸發
389      */
390     @Override
391     protected void onFinishInflate() {
392         // TODO Auto-generated method stub
393         super.onFinishInflate();
394         if (getChildCount() < 2) {
395             throw new IllegalAccessError(
396                     "佈局至少有2個孩子. Your ViewGroup must have 2 children at least");
397         }
398         if (!(getChildAt(0) instanceof ViewGroup && getChildAt(1) instanceof ViewGroup)) {
399             throw new IllegalArgumentException(
400                     "子View必須是ViewGroup的子類. Your children must be an instance of ViewGroup");
401         }
402         mLeftContent = (ViewGroup) getChildAt(0);
403         mMainContent = (ViewGroup) getChildAt(1);
404     }
405 
406     /**
407      * 當view的大小發生變化時觸發
408      */
409     private int mRange;
410     private int mHeight;
411     private int mWidth;
412 
413     @Override
414     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
415         // 當尺寸有變化的時候調用
416         super.onSizeChanged(w, h, oldw, oldh);
417         mHeight = getMeasuredHeight();
418         mWidth = getMeasuredWidth();
419         mRange = (int) (mWidth * 0.6f);
420     }
421 
422 }

如下是主程式代碼

  1 package com.demo.sb.main;
  2 
  3 import com.demo.sb.mainfram.TentcentOneFragment;
  4 import com.demo.sb.mainfram.TentcentThreeFragment;
  5 import com.demo.sb.mainfram.TentcentTwoFragment;
  6 import com.demo.sb.utils.Utils;
  7 import com.demo.sb.widget.DragLayout;
  8 import com.demo.sb.widget.DragLayout.OnDragStatusChangeListener;
  9 import com.demo.sb.widget.MyListLinearLayout;
 10 import com.demo.suibian.R;
 11 import com.nineoldandroids.animation.ObjectAnimator;
 12 import com.nineoldandroids.view.ViewHelper;
 13 
 14 import android.os.Bundle;
 15 import android.support.v4.app.FragmentActivity;
 16 import android.support.v4.app.FragmentManager;
 17 import android.support.v4.app.FragmentTransaction;
 18 import android.view.View;
 19 import android.view.Window;
 20 import android.view.animation.CycleInterpolator;
 21 import android.widget.ImageView;
 22 import android.widget.RadioGroup;
 23 import android.widget.RadioGroup.OnCheckedChangeListener;
 24 import android.widget.TextView;
 25 
 26 /**
 27  * 側滑菜單
 28  * 
 29  * @author Administrator
 30  * 
 31  */
 32 public class Activity_Tencent extends FragmentActivity {
 33 
 34     private RadioGroup rg_tencent_mian;
 35     // private FrameLayout fl_tencent_content;
 36     private ImageView iv_header;
 37     private TextView tv_header;
 38 
 39     private TentcentOneFragment oneFragment;
 40     private TentcentTwoFragment twoFragment;
 41     private TentcentThreeFragment threeFragment;
 42     private static DragLayout mDragLayout;
 43 
 44     @Override
 45     protected void onCreate(Bundle savedInstanceState) {
 46         // TODO Auto-generated method stub
 47         super.onCreate(savedInstanceState);
 48         requestWindowFeature(Window.FEATURE_NO_TITLE);
 49         setContentView(R.layout.activity_tencent);
 50 
 51         initView();
 52         initData();
 53 
 54     }
 55 
 56     private void initView() {
 57         // TODO Auto-generated method stub
 58         rg_tencent_mian = (RadioGroup) findViewById(R.id.rg_tencent_mian);
 59         iv_header = (ImageView) findViewById(R.id.iv_header);
 60         tv_header = (TextView) findViewById(R.id.tv_header);
 61         MyListLinearLayout mLayout = (MyListLinearLayout) findViewById(R.id.mll);
 62         mDragLayout = (DragLayout) findViewById(R.id.dl);
 63         // 設置引用
 64         mLayout.setDraglayout(mDragLayout);
 65 
 66         mDragLayout.setDragStatusListener(new OnDragStatusChangeListener() {
 67 
 68             @Override
 69             public void onOpen() {
 70                 // TODO Auto-generated met

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 開通博客以來已經約莫1個月了。幾次想提筆寫寫東西,但總是由於各種各樣的原因並沒有開始。現在,年假剛結束,項目也還沒有開始,但最終促使我寫這篇博客的是,看了一篇博友寫的新年計劃,說是要在新的一年中寫50篇博客,我也心血來潮的定下了這樣的目標。把年前項目中用到的FragmentTabHost在這裡總結一
  • 需求:在一個數組裡面,將在這個數組中的並且在另一個數組裡面的元素過濾掉。 即:在一個數組dataArray裡面,將在dataArray數組中的並且在filteredArray數組裡面的元素過濾掉。 //iOS-篩選數組內的元素 //在dataArray中裡面,將在dataArray中的並且在filt
  • 今天早上同事說咱們的證書無法使用了,顯示“此證書的簽發者無效”。一開始以為誰誤操作了證書,查看後發現所有證書都無效了。查了會才發下原來是Apple Worldwide Developer Relations Certification Authority Intermediate Certifica
  • 嗷嗚嗷嗚嗷嗚 1 // 將視圖作為屬性方便後面執行多個不同動畫 2 _myView = [[UIView alloc] init]; 3 _myView.layer.position = CGPointMake(100, 100); 4 _myView.layer.bounds = CGRectMa
  • 今天用Xcode打包IPA文件給同事,結果提示import時,提示證書missing,找了半天沒發現問題,後來打開鑰匙串,發現證書全失效了!!!嚇死寶寶了~~~~(>_<)~~~~ 然後,處理它。 1.打開鑰匙串 2.進行如下圖操作,打開證書信息雙擊或右鍵均可 3.再次去打包,成功 註意:分享轉載請
  • Moshi 是一個現代化的JSON庫針對Android和Java。它可以很容易地解析JSON成Java對象: String json = ...; Moshi moshi = new Moshi.Builder().build(); JsonAdapter<BlackjackHand> jsonAd
  • 自定義視圖,視圖控制器,視圖控制器指定視圖,loadView,viewDidLoad,MVC,屏幕旋轉,記憶體警告
  • 迴圈廣告我們在開發中已經是熟得不能再熟了,今天整理這篇scrollview三屏復用廣告 原理使用scrollview里的三個imageview分別去載入不同的圖片,用少量的資源來顯示大量或不確定的廣告數量,不然如果用普通方法實現廣告,難道10個廣告用12個scrollview的contentsize
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...