對於滑動菜單欄SlidingMenu,你們應該都不陌生,在市場上的一些APP應用裏常常能夠見到,好比人人網,FaceBook等。android
前段時間QQ5.0版本出來後也採用了這種設計風格:(下面是效果圖)git
以前在GitHub上看到過關於此設計風格的開源項目,它只須要引入對應的類庫,就能夠定製靈活、各類陰影和漸變以及動畫的滑動效果的側滑菜單。github
這裏是關於開源組件的介紹網址:https://github.com/jfeinstein10/SlidingMenuapp
但做爲開發人員,在學習階段仍是建議儘量的去本身實現,因此今天我不講此開源項目的使用方式,咱們用自定義HorizontalScrollView來實現此效果。eclipse
下面先看下實現效果圖:ide
上圖的效果是用自定義HorizontalScrollView來實現的,在HorizontalScrollView裏潛入一個橫向排列的線性佈局,而後在線性佈局裏分別加入菜單佈局和內容佈局,在咱們初始化的時候把HorizontalScrollView的滾動條向左拉至左邊菜單距離便可實現菜單佈局的隱藏,關於縮放,移動效果咱們可使用開源動畫庫nineoldandroids來實現,只須要幾行代碼。佈局
好了,接着直接上代碼吧:學習
首先,先看下佈局文件:動畫
一、菜單欄佈局文件:ui
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent"> 5 6 <LinearLayout 7 android:layout_width="match_parent" 8 android:layout_height="match_parent" 9 android:orientation="vertical" > 10 11 <RelativeLayout 12 android:layout_width="match_parent" 13 android:layout_height="wrap_content" 14 android:layout_centerInParent="true" > 15 16 <ImageView 17 android:id="@+id/menuimage1" 18 android:layout_width="50dp" 19 android:layout_height="50dp" 20 android:layout_centerVertical="true" 21 android:layout_marginLeft="20dp" 22 android:layout_marginTop="20dp" 23 android:src="@drawable/img_1" /> 24 25 <TextView 26 android:id="@+id/menutext1" 27 android:layout_width="wrap_content" 28 android:layout_height="wrap_content" 29 android:layout_centerVertical="true" 30 android:layout_marginLeft="20dp" 31 android:layout_marginTop="20dp" 32 android:layout_toRightOf="@id/menuimage1" 33 android:text="菜單一" 34 android:textColor="@android:color/white" 35 android:textSize="20dp" /> 36 </RelativeLayout> 37 38 39 <RelativeLayout 40 android:layout_width="match_parent" 41 android:layout_height="wrap_content" 42 android:layout_centerInParent="true" > 43 44 <ImageView 45 android:id="@+id/menuimage2" 46 android:layout_width="50dp" 47 android:layout_height="50dp" 48 android:layout_centerVertical="true" 49 android:layout_marginLeft="20dp" 50 android:layout_marginTop="20dp" 51 android:src="@drawable/img_2" /> 52 53 <TextView 54 android:id="@+id/menutext2" 55 android:layout_width="wrap_content" 56 android:layout_height="wrap_content" 57 android:layout_centerVertical="true" 58 android:layout_marginLeft="20dp" 59 android:layout_marginTop="20dp" 60 android:layout_toRightOf="@id/menuimage2" 61 android:text="菜單二" 62 android:textColor="@android:color/white" 63 android:textSize="20dp" /> 64 </RelativeLayout> 65 66 <RelativeLayout 67 android:layout_width="match_parent" 68 android:layout_height="wrap_content" 69 android:layout_centerInParent="true" > 70 71 <ImageView 72 android:id="@+id/menuimage3" 73 android:layout_width="50dp" 74 android:layout_height="50dp" 75 android:layout_centerVertical="true" 76 android:layout_marginLeft="20dp" 77 android:layout_marginTop="20dp" 78 android:src="@drawable/img_3" /> 79 80 <TextView 81 android:id="@+id/menutext3" 82 android:layout_width="wrap_content" 83 android:layout_height="wrap_content" 84 android:layout_centerVertical="true" 85 android:layout_marginLeft="20dp" 86 android:layout_marginTop="20dp" 87 android:layout_toRightOf="@id/menuimage3" 88 android:text="菜單三" 89 android:textColor="@android:color/white" 90 android:textSize="20dp" /> 91 </RelativeLayout> 92 93 94 <RelativeLayout 95 android:layout_width="match_parent" 96 android:layout_height="wrap_content" 97 android:layout_centerInParent="true" > 98 99 <ImageView 100 android:id="@+id/menuimage4" 101 android:layout_width="50dp" 102 android:layout_height="50dp" 103 android:layout_centerVertical="true" 104 android:layout_marginLeft="20dp" 105 android:layout_marginTop="20dp" 106 android:src="@drawable/img_4" /> 107 108 <TextView 109 android:id="@+id/menutext4" 110 android:layout_width="wrap_content" 111 android:layout_height="wrap_content" 112 android:layout_centerVertical="true" 113 android:layout_marginLeft="20dp" 114 android:layout_marginTop="20dp" 115 android:layout_toRightOf="@id/menuimage4" 116 android:text="菜單四" 117 android:textColor="@android:color/white" 118 android:textSize="20dp" /> 119 </RelativeLayout> 120 121 122 <RelativeLayout 123 android:layout_width="match_parent" 124 android:layout_height="wrap_content" 125 android:layout_centerInParent="true" > 126 127 <ImageView 128 android:id="@+id/menuimage5" 129 android:layout_width="50dp" 130 android:layout_height="50dp" 131 android:layout_centerVertical="true" 132 android:layout_marginLeft="20dp" 133 android:layout_marginTop="20dp" 134 android:src="@drawable/img_5" /> 135 136 <TextView 137 android:id="@+id/menutext5" 138 android:layout_width="wrap_content" 139 android:layout_height="wrap_content" 140 android:layout_centerVertical="true" 141 android:layout_marginLeft="20dp" 142 android:layout_marginTop="20dp" 143 android:layout_toRightOf="@id/menuimage5" 144 android:text="菜單五" 145 android:textColor="@android:color/white" 146 android:textSize="20dp" /> 147 </RelativeLayout> 148 </LinearLayout> 149 150 </RelativeLayout>
二、主內容佈局文件:
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:background="@drawable/img_frame_background" > 6 7 <com.example.sidesliptest.MyHorizontalScrollView 8 android:layout_height="match_parent" 9 android:layout_width="match_parent" 10 android:scrollbars="none" 11 > 12 <LinearLayout 13 android:layout_height="match_parent" 14 android:layout_width="match_parent" 15 android:orientation="horizontal" 16 > 17 <include layout="@layout/left_menu"/> 18 <LinearLayout 19 android:layout_width="match_parent" 20 android:layout_height="match_parent" 21 android:background="@drawable/qq" 22 ></LinearLayout> 23 24 </LinearLayout> 25 26 </com.example.sidesliptest.MyHorizontalScrollView> 27 28 </RelativeLayout>
三、自定義View(HorizontalScrollView)類:
自定義Viewi實現步驟:
一、繼承要自定義View的類,並實現帶有參數的構造方法
二、重寫onMeasure(肯定自定義View的大小)和onLayout(肯定自定義View的位置)方法
關於HorizontalScrollView的滑動,咱們能夠用onScrollChanged來監聽參數L:
打印日誌:能夠發現,當滾動條向左(畫面向右滑動)的時候,L的值是逐漸增大的,因此咱們能夠經過它來做爲動畫的變化梯度值。
註釋很全,具體看註釋吧。
1 package com.example.sidesliptest; 2 3 import android.content.Context; 4 import android.util.AttributeSet; 5 import android.util.DisplayMetrics; 6 import android.util.Log; 7 import android.util.TypedValue; 8 import android.view.MotionEvent; 9 import android.view.ViewGroup; 10 import android.view.WindowManager; 11 import android.widget.HorizontalScrollView; 12 import android.widget.LinearLayout; 13 14 import com.nineoldandroids.view.ViewHelper; 15 16 public class MyHorizontalScrollView extends HorizontalScrollView { 17 18 // 在HorizontalScrollView有個LinearLayout 19 private LinearLayout linearLayout; 20 // 菜單,內容頁 21 private ViewGroup myMenu; 22 private ViewGroup myContent; 23 //菜單寬度 24 private int myMenuWidth; 25 26 // 屏幕寬度 27 private int screenWidth; 28 // 菜單與屏幕右側的距離(dp) 29 private int myMenuPaddingRight = 50; 30 31 // 避免屢次調用onMeasure的標誌 32 private boolean once = false; 33 34 /** 35 * 自定義View須要實現帶有Context、AttributeSet這2個參數的構造方法,不然自定義參數會出錯 36 * 當使用了自定義屬性時,會調用此構造方法 37 * 38 * @param context 39 * @param attrs 40 */ 41 public MyHorizontalScrollView(Context context, AttributeSet attrs) { 42 super(context, attrs); 43 // 獲取屏幕寬度 44 WindowManager windowManager = (WindowManager) context 45 .getSystemService(Context.WINDOW_SERVICE); 46 DisplayMetrics outMetrics = new DisplayMetrics(); 47 windowManager.getDefaultDisplay().getMetrics(outMetrics); 48 screenWidth = outMetrics.widthPixels;// 屏幕寬度 49 50 // 將dp轉換px 51 myMenuPaddingRight = (int) TypedValue.applyDimension( 52 TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources() 53 .getDisplayMetrics()); 54 55 } 56 57 /** 58 * 設置子View的寬高,決定自身View的寬高,每次啓動都會調用此方法 59 */ 60 @Override 61 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 62 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 63 if (!once) {//使其只調用一次 64 // this指的是HorizontalScrollView,獲取各個元素 65 linearLayout = (LinearLayout) this.getChildAt(0);// 第一個子元素 66 myMenu = (ViewGroup) linearLayout.getChildAt(0);// HorizontalScrollView下LinearLayout的第一個子元素 67 myContent = (ViewGroup) linearLayout.getChildAt(1);// HorizontalScrollView下LinearLayout的第二個子元素 68 69 // 設置子View的寬高,高於屏幕一致 70 myMenuWidth=myMenu.getLayoutParams().width = screenWidth - myMenuPaddingRight;// 菜單的寬度=屏幕寬度-右邊距 71 myContent.getLayoutParams().width = screenWidth;// 內容寬度=屏幕寬度 72 // 決定自身View的寬高,高於屏幕一致 73 // 因爲這裏的LinearLayout裏只包含了Menu和Content因此就不須要額外的去指定自身的寬 74 once = true; 75 } 76 } 77 78 //設置View的位置,首先,先將Menu隱藏(在eclipse中ScrollView的畫面內容(非滾動條)正數表示向左移,向上移) 79 @Override 80 protected void onLayout(boolean changed, int l, int t, int r, int b) { 81 super.onLayout(changed, l, t, r, b); 82 //剛載入界面的時候隱藏Menu菜單也就是ScrollView向左滑動菜單自身的大小 83 if(changed){ 84 this.scrollTo(myMenuWidth, 0);//向左滑動,至關於把右邊的內容頁拖到正中央,菜單隱藏 85 } 86 87 } 88 89 @Override 90 public boolean onTouchEvent(MotionEvent ev) { 91 int action=ev.getAction(); 92 switch (action) { 93 case MotionEvent.ACTION_UP: 94 int scrollX=this.getScrollX();//滑動的距離scrollTo方法裏,也就是onMeasure方法裏的向左滑動那部分 95 if(scrollX>=myMenuWidth/2){ 96 this.smoothScrollTo(myMenuWidth,0);//向左滑動展現內容 97 }else{ 98 this.smoothScrollTo(0, 0); 99 } 100 return true; 101 } 102 return super.onTouchEvent(ev); 103 } 104 105 106 @Override 107 protected void onScrollChanged(int l, int t, int oldl, int oldt) { 108 super.onScrollChanged(l, t, oldl, oldt); 109 Log.i("tuzi",l+""); 110 float scale = l * 1.0f / myMenuWidth; // 1 ~ 0 111 121 float rightScale = 0.7f + 0.3f * scale; 122 float leftScale = 1.0f - scale * 0.3f; 123 float leftAlpha = 0.6f + 0.4f * (1 - scale); 124 125 // 調用屬性動畫,設置TranslationX 126 ViewHelper.setTranslationX(myMenu, myMenuWidth * scale * 0.8f); 127 128 ViewHelper.setScaleX(myMenu, leftScale); 129 ViewHelper.setScaleY(myMenu, leftScale); 130 ViewHelper.setAlpha(myMenu, leftAlpha); 131 // 設置內容縮放的中心點 132 ViewHelper.setPivotX(myContent, 0); 133 ViewHelper.setPivotY(myContent, myContent.getHeight() / 2); 134 ViewHelper.setScaleX(myContent, rightScale); 135 ViewHelper.setScaleY(myContent, rightScale); 136 } 137 138 }
四、主程序類:
package com.example.sidesliptest; import android.app.Activity; import android.os.Bundle; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); } }
圖片素材:http://pan.baidu.com/s/1kTkjmAj
做者:Balla_兔子
出處:http://www.cnblogs.com/lichenwei/本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文連接。正在看本人博客的這位童鞋,我看你氣度不凡,談吐間隱隱有王者之氣,往後必有一番做爲!旁邊有「推薦」二字,你就順手把它點了吧,相得準,我分文不收;相不許,你也好回來找我!