編輯:關於Android編程
上一篇博客帶大家實現了:Android 自定義控件打造史上最簡單的側滑菜單 ,有兄弟看了以後說,你這滑動菜單過時了呀~QQ5.0的效果還不錯~~嗯,的確,上一篇也承諾過,稍微修改上一篇的代碼,實現QQ5.0側滑菜單~~好了,下面就開始為大家展示寫一個類QQ的側滑有多easy ~!
首先對比一下我們上篇的實現距離QQ的效果還有多遠:
差距還是蠻大的
區別1、QQ的內容區域會伴隨菜單的出現而縮小
區別2、QQ的側滑菜單給人的感覺是隱藏在內容的後面,而不是拖出來的感覺
區別3、QQ的側滑菜單有一個縮放以及透明度的效果~
那麼我們如何能做到呢:
對於區別1:這個好辦,我們可以在滑動的時候,不斷的改變內容區域的大小;如何改變呢?我們在菜單出現的整個過程中,不斷記錄菜單顯示的寬度與其總寬度的比值,是個從0到1的過程,然後把0~1轉化為1~0.7(假設內容區域縮小至0.7);不斷去縮小內容區域;
對於區別3:也比較好辦,上面已經可以得到0到1的這個值了,那麼縮放和透明度的動畫就不在話下了;
對於區別2:我們使用的HorizontalScrollView,然後水平放置了菜單和內容,如何讓菜單可以隱藏到內容的後面呢?其實也比較簡單,在菜單出現的過程中,不斷設置菜單的x方向的偏移量;0的時候完全隱藏,0.3的時候,隱藏x方向偏移量為0.7個寬度,類推~~~
好了,分析完畢,那麼對於這些動畫用什麼實現最好呢?
想都不用想,屬性動畫哈,如果你對屬性動畫不了解,可以參:Android 屬性動畫(Property Animation) 完全解析 (上)和Android 屬性動畫(Property Animation) 完全解析 (下)
布局文件神馬的,都和上一篇一模一樣,這裡就不重復貼代碼了,不了解的,先看下上一篇;
先看一下上一篇我們已經實現的完整代碼:
package com.example.zhy_slidingmenu; import android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; import android.util.TypedValue; import android.view.MotionEvent; import android.view.ViewGroup; import android.widget.HorizontalScrollView; import android.widget.LinearLayout; import com.zhy.utils.ScreenUtils; public class SlidingMenu extends HorizontalScrollView { /** * 屏幕寬度 */ private int mScreenWidth; /** * dp */ private int mMenuRightPadding; /** * 菜單的寬度 */ private int mMenuWidth; private int mHalfMenuWidth; private boolean isOpen; private boolean once; public SlidingMenu(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mScreenWidth = ScreenUtils.getScreenWidth(context); TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.SlidingMenu, defStyle, 0); int n = a.getIndexCount(); for (int i = 0; i < n; i++) { int attr = a.getIndex(i); switch (attr) { case R.styleable.SlidingMenu_rightPadding: // 默認50 mMenuRightPadding = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 50f, getResources().getDisplayMetrics()));// 默認為10DP break; } } a.recycle(); } public SlidingMenu(Context context) { this(context, null, 0); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { /** * 顯示的設置一個寬度 */ if (!once) { LinearLayout wrapper = (LinearLayout) getChildAt(0); ViewGroup menu = (ViewGroup) wrapper.getChildAt(0); ViewGroup content = (ViewGroup) wrapper.getChildAt(1); mMenuWidth = mScreenWidth - mMenuRightPadding; mHalfMenuWidth = mMenuWidth / 2; menu.getLayoutParams().width = mMenuWidth; content.getLayoutParams().width = mScreenWidth; } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if (changed) { // 將菜單隱藏 this.scrollTo(mMenuWidth, 0); once = true; } } @Override public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); switch (action) { // Up時,進行判斷,如果顯示區域大於菜單寬度一半則完全顯示,否則隱藏 case MotionEvent.ACTION_UP: int scrollX = getScrollX(); if (scrollX > mHalfMenuWidth) { this.smoothScrollTo(mMenuWidth, 0); isOpen = false; } else { this.smoothScrollTo(0, 0); isOpen = true; } return true; } return super.onTouchEvent(ev); } /** * 打開菜單 */ public void openMenu() { if (isOpen) return; this.smoothScrollTo(0, 0); isOpen = true; } /** * 關閉菜單 */ public void closeMenu() { if (isOpen) { this.smoothScrollTo(mMenuWidth, 0); isOpen = false; } } /** * 切換菜單狀態 */ public void toggle() { if (isOpen) { closeMenu(); } else { openMenu(); } } }
現在我們開始解決那3個區別,已經選擇了使用屬性動畫,現在決定動畫效果應該加在哪兒?
不用說,我用大腿想一想都應該是在ACTION_MOVE中,是的,ACTION_MOVE中的確可以,不斷獲取當前的getScrollX / mMenuWidth,不斷改變菜單的透明度,縮放,X方向的偏移量;不斷改變內容區域的寬度和高度;
說一下,起初我也是在MOVE中這麼做的,但是呢,出現兩個問題:
1、動畫效果並不是很流暢,特別是菜單,有抖動的效果;
2、用戶抬起後,還需要在UP裡面,繼續未完成的動畫,就是說,你的透明度、縮放神馬的,當用戶抬起以後就需要自動變化了;
於是乎,我就開始換了個方向,既然是SrollView,肯定有一個ScrollChanged方法,功夫不負有心人,真心這麼個方法:
@Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { }這個方法只要scrollChanged就會觸發,l就是我們需要的scrollX,太贊了~~~
我們在onScrollChanged裡面,拿到 l 也就是個getScrollX,即菜單已經顯示的寬度值;
float scale = l * 1.0f / mMenuWidth;
有了這個區間,就可以根據這個區間設置動畫了;
1、首先是內容區域的縮放比例計算:
我們准備讓在菜單出現的過程中,讓內容區域從1.0~0.8進行變化~~
那麼怎麼把1.0~0.0轉化為1.0~0.8呢,其實很簡單了:
float rightScale = 0.8f + scale * 0.2f; (scale 從1到0 ),是不是哦了~
接下來還有3個動畫:
2、菜單的縮放比例計算
仔細觀察了下QQ,菜單大概縮放變化是0.7~1.0
float leftScale = 1 - 0.3f * scale;
3、菜單的透明度比例:
我們設置為0.6~1.0;即:0.6f + 0.4f * (1 - scale)
4、菜單的x方向偏移量:
看一下QQ,並非完全從被內容區域覆蓋,還是有一點拖出的感覺,所以我們的偏移量這麼設置:
tranlateX = mMenuWidth * scale * 0.6f ;剛開始還是讓它隱藏一點點~~~
說了這麼說,其實到上一篇史上最簡單的側滑,到QQ5.0的效果的轉變,只需要幾行代碼~~
@Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); float scale = l * 1.0f / mMenuWidth; float leftScale = 1 - 0.3f * scale; float rightScale = 0.8f + scale * 0.2f; ViewHelper.setScaleX(mMenu, leftScale); ViewHelper.setScaleY(mMenu, leftScale); ViewHelper.setAlpha(mMenu, 0.6f + 0.4f * (1 - scale)); ViewHelper.setTranslationX(mMenu, mMenuWidth * scale * 0.6f); ViewHelper.setPivotX(mContent, 0); ViewHelper.setPivotY(mContent, mContent.getHeight() / 2); ViewHelper.setScaleX(mContent, rightScale); ViewHelper.setScaleY(mContent, rightScale); }
是騾子是馬,拉出來溜溜
菜單欄需要ListView的拖動也是不會沖突了,上篇已經測試了;
關於動畫屬性的范圍:上面介紹的特別清楚,比如內容我們是最小顯示0.8,你要是喜歡0.6,自己去修改一下;包括偏移量,透明度等范圍;
因為上一篇已經寫了如何把屬性抽取成自定義的屬性;所以這裡就沒有抽取了,不然總覺得是在重復~
嗯,最近還有寫APP的側滑,是這樣的,就是菜單欄完全隱藏在內容區域下面,如果需要這樣需求的:
其實我還滿喜歡這樣效果的。
實現呢,注釋幾行代碼就實現了:
@Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); float scale = l * 1.0f / mMenuWidth; // float leftScale = 1 - 0.3f * scale; // float rightScale = 0.8f + scale * 0.2f; // // ViewHelper.setScaleX(mMenu, leftScale); // ViewHelper.setScaleY(mMenu, leftScale); // ViewHelper.setAlpha(mMenu, 0.6f + 0.4f * (1 - scale)); ViewHelper.setTranslationX(mMenu, mMenuWidth * scale ); // ViewHelper.setPivotX(mContent, 0); // ViewHelper.setPivotY(mContent, mContent.getHeight() / 2); // ViewHelper.setScaleX(mContent, rightScale); // ViewHelper.setScaleY(mContent, rightScale); }
好了,雖說最終的實現看起來還是很簡單的,看起來,嗯~~但是從無到有的這個過程還是不容易的~~各種嘗試,我能說我連蹲坑都在滑QQ的菜單觀察麼~哈,見笑了;博客中也寫出了過程中失敗的嘗試,希望能夠更好的讓大家在裡面學到些有用的東西~~YEAH!! 就到這,沒事就留個言~~~再不留言,我就來個源碼請留下郵箱,嘿嘿,開個玩笑~
ExpandableListView是一個垂直滾動顯示兩級列表項的視圖,與ListView不同的是,它可以有兩層:每一層都能夠被獨立的展開並顯示其子項。好友QQ列表,可以
現在很多Android市場中都能找到關於美女的應用,比如 撕開美女衣服、吹裙子等。 這些應用的下載量挺大的,作為Android的開發人員或者一名技術人員我們不能只局限在欣
手機qq聊天字體用膩了怎麼修改,字體顏色又是怎麼修改的呢?具體操作如下,一起來看看吧!如何修改手機qq字體顏色用手機管理器進入 E:System→
最近想把學習Android過程中的Handler使用經驗寫下來,供自己以後查看,也與大家一起分享。使用Handler其實不得不與Android中的線程或者說Java中的多