国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android使用ViewDragHelper實現仿QQ6.0側滑界面(一)

2020-04-11 10:51:34
字體:
來源:轉載
供稿:網友

QQ是大家離不開的聊天工具,方便既實用,自從qq更新至6.0之后,側滑由原來的劃出后主面板縮小變成了左右平滑,在外觀上有了很大的提升,于是我就是嘗試理解下里面的各種邏輯,結合相關資料,研究研究。

知道這里面的一個主要類是ViewDragHelper,那么首先我們要先來了解一下這個ViewDragHelper類,正所謂打蛇打七寸,我們就先來看看官方文檔怎么介紹的,有什么奇特的功能。

首先繼承:

java.lang.Object
android.support.v4.widget.ViewDragHelper
直接父類是Object。

類概述

ViewDragHelper is a utility class for writing custom ViewGroups. It offers a number of useful operations and state tracking for allowing a user to drag and reposition views within their parent ViewGroup.

他是一個編寫自定義ViewGroup的工具類,本省提供了許多有用的方法和狀態允許用戶去拖拽和繪制他們在父ViewGroup中的軌跡和位置。

Nested Classes(嵌套類)

ViewDragHelper.Callback
A Callback is used as a communication channel with the ViewDragHelper back to the parent view using it.

一個回調是用作ViewDragHelper和他的父view的通信的接口

一個公開靜態方法:

 

我們可以知道,ViewDragHelper是通過create()方法構造出來。這個在后面會有詳細介紹。

讓我們在來看下需要用到的里面的幾個方法:

public boolean tryCaptureView(View child, int pointerId) {}public int getViewHorizontalDragRange(View child) {}public int clampViewPositionHorizontal(View child, int left, int dx) {}public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {}public void onViewReleased(View releasedChild, float xvel, float yvel) {} 

上面的幾個方法,會在代碼中有詳細的注釋,在這里只是看下我們需要重寫的方法

好了哈,說了這么多,我們就先來個簡單的,就是可以實現拖拽(相信當你的兩個view可以拖拽的時候,你會發現,哦這么簡單幾步么):

第一步實現拖拽功能(簡單3步實現

//1、通過靜態方法初始化操作mDragHelper = ViewDragHelper.create(this, mCallback);/*** 2、傳遞觸摸事件** @param ev* @return*/@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {//讓自己的控件自行判斷是否去攔截return mDragHelper.shouldInterceptTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent event) {try {//自己去處理觸摸事件mDragHelper.processTouchEvent(event);} catch (Exception e) {e.printStackTrace();}//返回true,這樣才能持續接收,要不然我們不會傳遞而是被攔截了return true;}ViewDragHelper.Callback mCallback = new ViewDragHelper.Callback() {/*** 根據返回結果決定當前child是否可以拖拽* 嘗試捕獲的時候調用,如果返回的是主面板,那么負面版是不能被調用的* @param child 當前被拖拽的view* @param pointerId 區分多點觸摸的id* @return 返回true 是都可以拖拽 * 返回child == mLeftContent 左側可以移動* 返回child == mMainContent 右側可以移動*/@Overridepublic boolean tryCaptureView(View child, int pointerId) {//這里要返回true,要不然不能拖拽return true;}/*** 根據建議值修正將要移動的位置 此時并沒有發生真正的移動(左右)** @param child 當前拖拽的view* @param left 新的位置的建議值 oldLeft + dx* @param dx 變化量 和變化之前位置的差值* @return*/@Overridepublic int clampViewPositionHorizontal(View child, int left, int dx) {//返回的拖拽的范圍,不對拖拽進行真正的限制,僅僅決定了動畫執行的速度return left;}};

好了,第一個效果圖可以出來了,就是可以拖拽了,是不是 很簡單的就實現了呢:

這里寫圖片描述 

但是,你要是做成這樣提交任務,是不是不想干活了哈,好了下面我們就來控制一下拖拽位置,不能讓他亂拖拽了哈。、

第二步,控制拖拽范圍

我們想要控制拖拽范圍,首先我們得需要拿到這兩個控件,取到有關這兩個控件的屬性,我們才能去操作。于是我們重寫了一下的方法:

/*** Finalize inflating a view from XML. This is called as the last phase* of inflation, after all child views have been added.* 當xml填充完的時候去掉用,在這里我們可以找到我們要去操控的那兩個布局* <p>Even if the subclass overrides onFinishInflate, they should always be* sure to call the super method, so that we get called.*/@Overrideprotected void onFinishInflate() {super.onFinishInflate();/*** 根據索引來找*//*** 得到左邊的布局*/mLeftContent = (ViewGroup) getChildAt(0);/*** 得到主main布局*/mMainContent = (ViewGroup) getChildAt(1);}

接下來我們就要來得到有關寬和高了,我們知道onMessure()中可以獲取,不過查看了一下,下面的這個方法也是可以獲取到的:

/*** 當尺寸變化的時候去調用* This is called during layout when the size of this view has changed* @param w* @param h* @param oldw* @param oldh*/@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);/*** 屏幕的寬度和高度*/mHeight = getMeasuredHeight();mWidth = getMeasuredWidth();/*** 自定義左側view拖拽出來的距離*/mRange = (int) (mWidth * 0.7);}

好了,有關我們需要的寬、高、拖拽距離我們已經獲取到了,那么我們接下來就要來限制了。

我們只需要在clampViewPositionHorizontal()方法中加入這個,就能限制主面板不能往左移,左面板只能移動到右側的mRange位置。(這里可以去嘗試一下哈)

if (child == mMainContent) {left = fixLeft(left);}/*** 修正方法* 根據范圍去修正左側的view的可見** @param left* @return*/private int fixLeft(int left) {if (left < 0) {return 0;} else if (left > mRange) {return mRange;}return left;}

這個時候,我們基本上的大致框架已經出來了,但是還是有一個問題,那就是雖然我們達到了滑動過的效果(右側的定了,但是當我們把LeftView滑動出來的時候,還是可以往右滑)我們要想辦法去限制,就是限制,左側的view我只能右滑mRange的距離這個時候我們就要查看方法了,哪個方法可以拿到變化的position的值,然后去改變:

/*** 當view位置改變的時候,處理要做的事情,更新狀態,伴隨動畫,重繪界面** 此時view已經發生了位置的改變** @param changedView 改變的位置view* @param left 新的左邊值* @param top* @param dx 水平變化量* @param dy*/@Overridepublic void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {super.onViewPositionChanged(changedView, left, top, dx, dy);int newLeft = left;//如果我們拖拽的是左面板if (changedView == mLeftContent) {//新的左側位置是我們的主面板的左側加上水平變化量newLeft = mMainContent.getLeft() + dx;}//進行修正(不能超出我們的規定的范圍)newLeft = fixLeft(newLeft);if (changedView == mLeftContent) {//當左面板移動之后,在強制放回去mLeftContent.layout(0, 0, 0 + mWidth, 0 + mHeight);mMainContent.layout(newLeft, 0, newLeft + mWidth, 0 + mHeight);}//兼容低版本 強制重繪invalidate();}

好了,這個時候我們的大致效果已經出來了,看下效果圖。(這里的中間出來的白到屬于錄制問題,親測沒問題)

這里寫圖片描述 

到這里,大致的拖拽已經可以實現了,當然了哈,我的現在布局就是下面的簡單的實現(要先加一些控件,這個自己在兩個LinearLayout中加入即可)

<?xml version="1.0" encoding="utf-8"?><com.example.qqsliding.DragLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.example.qqsliding.MainActivity"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:background="@mipmap/sidebar_bg"></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:background="#FFFFFF"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="50dp"android:background="#0CB8F6"android:gravity="center_vertical"><ImageViewandroid:layout_width="30dp"android:layout_height="30dp"android:layout_marginLeft="15dp"android:src="@mipmap/icon_avatar_white"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerHorizontal="true"android:text="Header"/><ImageViewandroid:layout_width="30dp"android:layout_height="30dp"android:layout_alignParentRight="true"android:layout_marginRight="15dp"android:src="@mipmap/icon_search"/></RelativeLayout></LinearLayout></com.example.qqsliding.DragLayout>

但是細心的可能會發現,我們拖拽的時候,特別生硬,那是因為我們沒有加上動畫效果,只是生生的給拖拽出來了,具體的加入動畫,定義回調效果,請通過本文學習Android滑動優化高仿QQ6.0側滑菜單(二),希望本文分享對大家有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 广丰县| 邯郸县| 平乡县| 枣阳市| 平顶山市| 杨浦区| 广州市| 铁岭市| 连平县| 洪泽县| 盖州市| 鸡西市| 德化县| 馆陶县| 彩票| 都兰县| 民乐县| 石台县| 枣强县| 澜沧| 广丰县| 聂拉木县| 郁南县| 紫阳县| 乐安县| 平远县| 易门县| 临猗县| 深州市| 高台县| 博客| 沁源县| 南华县| 简阳市| 邛崃市| 武隆县| 曲周县| 晋城| 晋城| 长丰县| 金湖县|