亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

Android自定義ViewGroup打造各種風格的SlidingMenu

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

上篇給大家介紹QQ5.0側滑菜單的視頻課程,對于側滑的時的動畫效果的實現有了新的認識,似乎打通了任督二脈,目前可以實現任意效果的側滑菜單了,感謝鴻洋大大!!

用的是HorizontalScrollView來實現的側滑菜單功能,HorizontalScrollView的好處是為我們解決了滑動功能,處理了滑動沖突問題,讓我們使用起來非常方便,但是滑動和沖突處理都是android中的難點,是我們應該掌握的知識點,掌握了這些,我們可以不依賴于系統的API,隨心所欲打造我們想要的效果,因此這篇文章我將直接自定義ViewGroup來實現側滑菜單功能

首先我們先來看一看效果圖,第一個效果圖是一個最普通的側滑菜單,我們一會兒會先做出這種側滑菜單,然后再在此基礎上實現另外兩個效果

第一種

這里寫圖片描述

第二種

這里寫圖片描述

第三種

這里寫圖片描述

實現第一種側滑菜單,繼承自ViewGroup

繼承自ViewGroup需要我們自己來測量,布局,實現滑動的效果,處理滑動沖突,這些都是一些新手無從下手的知識點,希望看了這篇文章后可以對大家有一個幫助

自定義ViewGroup的一般思路是重寫onMeasure方法,在onMeasure方法中調用measureChild來測量子View,然后調用setMeasuredDimension來測量自己的大小。然后重寫onLayout方法,在onLayout中調用子View的layout方法來確定子View的位置,下面我們先來做好這兩件工作

這里寫圖片描述

初始時候我們的Content應該是顯示在屏幕中的,而Menu應該是顯示在屏幕外的。當Menu打開時,應該是這種樣子的

這里寫圖片描述 

mMenuRightPadding是Menu距屏幕右側的一個距離,因為我們Menu打開后,Content還是會留一部分,而不是完全隱藏的

public class MySlidingMenu extends ViewGroup {public MySlidingMenu(Context context) {this(context, null, 0);}public MySlidingMenu(Context context, AttributeSet attrs) {this(context, attrs, 0);}public MySlidingMenu(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);DisplayMetrics metrics = new DisplayMetrics();WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);wm.getDefaultDisplay().getMetrics(metrics);//獲取屏幕的寬和高mScreenWidth = metrics.widthPixels;mScreenHeight = metrics.heightPixels; //設置Menu距離屏幕右側的距離,convertToDp是將代碼中的100轉換成100dpmMenuRightPadding = convertToDp(context,100); }@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//拿到Menu,Menu是第0個孩子mMenu = (ViewGroup) getChildAt(0);//拿到Content,Content是第1個孩子mContent = (ViewGroup) getChildAt(1);//設置Menu的寬為屏幕的寬度減去Menu距離屏幕右側的距離mMenuWidth = mMenu.getLayoutParams().width = mScreenWidth - mMenuRightPadding;//設置Content的寬為屏幕的寬度mContentWidth = mContent.getLayoutParams().width = mScreenWidth;//測量MenumeasureChild(mMenu,widthMeasureSpec,heightMeasureSpec);//測量ContentmeasureChild(mContent, widthMeasureSpec, heightMeasureSpec);//測量自己,自己的寬度為Menu寬度加上Content寬度,高度為屏幕高度setMeasuredDimension(mMenuWidth + mContentWidth, mScreenHeight);}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {//擺放Menu的位置,根據上面圖可以確定上下左右的坐標mMenu.layout(-mMenuWidth, 0, 0, mScreenHeight);//擺放Content的位置mContent.layout(0, 0, mScreenWidth, mScreenHeight);}/*** 將傳進來的數轉化為dp*/private int convertToDp(Context context , int num){return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,num,context.getResources().getDisplayMetrics());}}

目前我們的側滑菜單中的兩個子View的位置應該是這個樣子

這里寫圖片描述 

左側菜單是隱藏在屏幕左側外部的,但是現在還不能滑動,如果想要實現滑動功能,我們可以使用View的scrollTo和scrollBy方法,這兩個方法的區別是scrollTo是直接將view移動到指定的位置,scrollBy是相對于當前的位置移動一個偏移量,所以我們應該重寫onTouchEvent方法,用來計算出當前手指的一個偏移量,然后使用scrollBy方法一點一點的移動,就形成了一個可以跟隨手指移動的view的動畫效果了

在寫代碼之前,我們先掃清一下障礙,我們先來弄清楚這些坐標是怎么回事

這里寫圖片描述
這里寫圖片描述
這里寫圖片描述

好了,把這些坐標弄清楚后,我們就簡單多了,下面直接看onTouchEvent方法

@Overridepublic boolean onTouchEvent(MotionEvent event) {int action = event.getAction();switch (action){case MotionEvent.ACTION_DOWN:mLastX = (int) event.getX();mLastY = (int) event.getY();break;case MotionEvent.ACTION_MOVE:int currentX = (int) event.getX();int currentY = (int) event.getY();//拿到x方向的偏移量int dx = currentX - mLastX;if (dx < 0){//向左滑動//邊界控制,如果Menu已經完全顯示,再滑動的話//Menu左側就會出現白邊了,進行邊界控制if (getScrollX() + Math.abs(dx) >= 0) {//直接移動到(0,0)位置,不會出現白邊scrollTo(0, 0);} else {//Menu沒有完全顯示呢//其實這里dx還是-dx,大家不用刻意去記//大家可以先使用dx,然后運行一下,發現//移動的方向是相反的,那么果斷這里加個負號就可以了scrollBy(-dx, 0);}}else{//向右滑動//邊界控制,如果Content已經完全顯示,再滑動的話//Content右側就會出現白邊了,進行邊界控制if (getScrollX() - dx <= -mMenuWidth) {//直接移動到(-mMenuWidth,0)位置,不會出現白邊scrollTo(-mMenuWidth, 0);} else {//Content沒有完全顯示呢//根據手指移動scrollBy(-dx, 0);}}mLastX = currentX;mLastY = currentY;break;}return true;}

現在我們的SlidingMenu依然是不能夠水平滑動的,但是listview可以豎直滑動,原因是我們的SlidingMenu默認是不攔截事件的,那么事件會傳遞給他的子View去執行,也就是說傳遞給了Content的ListView去執行了,所以listview是可以滑動的,為了簡單,我們先重寫onInterceptTouchEvent方法,我們返回true,讓SlidingMenu攔截事件,我們的SlidingMenu就能夠滑動了,但是ListView是不能滑動的,等下我們會進行滑動沖突的處理,現在先實現SlidingMenu的功能

@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {return true;}

好了,現在我們可以自由的滑動我們的SlidingMenu了,并且進行了很好的邊界控制,現在我們再添加個功能,就是當Menu打開大于二分之一時,松開手指,Menu自動打開。當Menu打開小于二分之一時,松開手指,Menu自動關閉。自動滑動的功能我們要借助Scroller來實現

我們在構造方法中初始化一個Scroller

public MySlidingMenu(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);...mScroller = new Scroller(context);...}

然后重寫computeScroll方法,這個方法是保證Scroller自動滑動的必須方法,這是一個模板方法,到哪里都這么些就好了

@Overridepublic void computeScroll() {if (mScroller.computeScrollOffset()){scrollTo(mScroller.getCurrX(), mScroller.getCurrY());invalidate();}}

接著我們在onTouchEvent的ACTION_UP中進行判斷,判斷當前menu打開了多少

case MotionEvent.ACTION_UP:if (getScrollX() < -mMenuWidth / 2){//打開Menu//調用startScroll方法,第一個參數是起始X坐標,第二個參數//是起始Y坐標,第三個參數是X方向偏移量,第四個參數是Y方向偏移量mScroller.startScroll(getScrollX(), 0, -mMenuWidth - getScrollX(), 0, 300);//設置一個已經打開的標識,當實現點擊開關自動打開關閉功能時會用到isOpen = true;//一定不要忘了調用這個方法重繪,否則沒有動畫效果invalidate();}else{//關閉Menu//同上mScroller.startScroll(getScrollX(), 0, -getScrollX(), 0, 300);isOpen = false;invalidate();}break;

關于startScroll中的startX和startY好判斷,那么dx和dy怎么計算呢?其實也非常簡單,比如我們startX坐標為30,我們想移動到-100,那么startX+dx = -100 亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

中文字幕精品影院| 久久躁日日躁aaaaxxxx| 国产亚洲精品久久| 国产精品爽黄69| 精品电影在线观看| 69视频在线免费观看| 黄色91在线观看| 日韩精品欧美激情| 亚洲综合在线小说| 日韩av有码在线| 亚洲奶大毛多的老太婆| 日韩久久免费电影| 欧美激情国内偷拍| 国内精品免费午夜毛片| 国产精品第1页| 性色av一区二区三区红粉影视| 亚洲激情小视频| 久久久久久久91| 欧美精品久久久久久久| 一本色道久久88综合日韩精品| 亚洲综合在线小说| 欧美噜噜久久久xxx| 欧美午夜xxx| 国产精品日韩久久久久| 国产69精品久久久久久| 欧美日韩另类字幕中文| 国产精品久久久久久久久久久新郎| 欧美日韩综合视频网址| 午夜美女久久久久爽久久| 中日韩午夜理伦电影免费| 欧美裸体xxxxx| 一区二区三区国产在线观看| 一二美女精品欧洲| 久久亚洲精品一区| 久久国产精品久久久| 九九精品在线播放| 91最新在线免费观看| 亚洲成人黄色在线| 日韩电影免费观看中文字幕| 欧美成人sm免费视频| 亚洲精品97久久| 亚洲欧美变态国产另类| 亚洲欧美综合另类中字| 色综合久久精品亚洲国产| 97精品视频在线| 热久久这里只有| 最近2019年手机中文字幕| 高清一区二区三区四区五区| 欧美日韩在线视频一区二区| 4438全国成人免费| 国产午夜精品视频| 成人黄在线观看| 日韩av高清不卡| 精品久久久999| 91国内揄拍国内精品对白| 日本精品免费观看| 亚洲图片在区色| 亚洲三级黄色在线观看| 中文字幕av一区中文字幕天堂| 日韩精品视频在线播放| 国产成人一区二区| 欧美日韩中文在线| 91精品中国老女人| 伊人久久综合97精品| 亚洲精品资源在线| 国产精品一香蕉国产线看观看| 成人性生交大片免费观看嘿嘿视频| 亚洲欧洲自拍偷拍| 久久久免费av| 97国产精品免费视频| 色樱桃影院亚洲精品影院| 国产欧美韩国高清| 久久久av网站| 成人444kkkk在线观看| 欧美在线激情网| 最近2019中文字幕大全第二页| 亚洲成人三级在线| 欧美激情欧美狂野欧美精品| 亚洲国产古装精品网站| 精品久久香蕉国产线看观看gif| 伊人久久五月天| 欧美午夜片欧美片在线观看| 日韩精品在线影院| 精品国产91久久久久久| 国产一区二区香蕉| 秋霞av国产精品一区| 国产日韩中文字幕在线| 国产精品扒开腿做爽爽爽视频| 成人444kkkk在线观看| 亚洲欧美制服第一页| 奇门遁甲1982国语版免费观看高清| 日韩欧美大尺度| 亚洲一区二区日本| 亚洲xxxx妇黄裸体| 亚洲精品自在久久| 色樱桃影院亚洲精品影院| 日韩欧美在线播放| 欧美色视频日本高清在线观看| 国产精品久久久久久久久免费| 久久久久久国产三级电影| 中文字幕亚洲在线| 久久91亚洲精品中文字幕| 97色在线观看| 亚洲欧美日韩一区二区三区在线| 在线日韩精品视频| 久久亚洲一区二区三区四区五区高| 九九热99久久久国产盗摄| 黄色精品一区二区| 国产免费一区二区三区在线能观看| 日韩电影在线观看中文字幕| 久久精品视频导航| 日韩精品极品在线观看播放免费视频| 欧美激情视频网| 51午夜精品视频| 日韩高清人体午夜| 亚洲一区亚洲二区亚洲三区| 国产精品视频精品视频| 国产欧美日韩免费看aⅴ视频| 亚洲天堂av在线免费观看| 欧美视频中文字幕在线| 欧美xxxx14xxxxx性爽| 日本久久久久久久久| 成人av电影天堂| 91在线视频成人| 亚洲影院色无极综合| 国产精品久久久久久久电影| 国产综合香蕉五月婷在线| 成人做爰www免费看视频网站| 日本在线观看天堂男亚洲| 亚洲女人被黑人巨大进入al| 久久久噜噜噜久久久| 国产视频久久久久久久| 成人精品一区二区三区电影黑人| 疯狂做受xxxx欧美肥白少妇| 日韩有码在线电影| 亚洲一区免费网站| 亚洲精品影视在线观看| 奇米四色中文综合久久| 欧美专区第一页| 九九久久精品一区| 亚洲精品动漫久久久久| 92看片淫黄大片看国产片| 成人免费在线视频网址| 欧美激情2020午夜免费观看| 国产69精品久久久久99| 亚洲一品av免费观看| 亚洲视频第一页| 欧美日韩一区免费| 国产一区二区日韩精品欧美精品| xxxxx91麻豆| 夜夜嗨av一区二区三区四区| 亚洲欧美另类国产| 欧美日韩国产黄| 成人激情电影一区二区| 久久综合亚洲社区| 亚洲大胆人体av| 欧美做爰性生交视频| 国产精品久久久久91| 国产91精品最新在线播放| 日韩国产精品一区| 国产美女久久久| 成人久久久久久| 亚洲色图校园春色| 精品久久久一区|