首先,我们会用到一个控件:HorizontalScrollView 从名字我们就能够了解到。这是一种水平滑动的控件,也就是当内容大于屏幕的宽度的时候,能够左右滑动来使超出屏幕的内容显示在屏幕上。
第一步:把菜单的布局简单的写出来
<span style="font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:14px;"><?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:layout_centerInParent="true" > <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" > <ImageView android:id="@+id/img1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" /> <TextView android:id="@+id/text1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="item1" android:layout_toRightOf="@id/img1" android:layout_centerVertical="true" /> </RelativeLayout> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" > <ImageView android:id="@+id/img2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" /> <TextView android:id="@+id/text2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="item1" android:layout_toRightOf="@id/img2" android:layout_centerVertical="true" /> </RelativeLayout> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" > <ImageView android:id="@+id/img3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" /> <TextView android:id="@+id/text3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="item1" android:layout_toRightOf="@id/img3" android:layout_centerVertical="true" /> </RelativeLayout> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" > <ImageView android:id="@+id/img4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" /> <TextView android:id="@+id/text4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="item1" android:layout_toRightOf="@id/img4" android:layout_centerVertical="true" /> </RelativeLayout> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" > <ImageView android:id="@+id/img5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" /> <TextView android:id="@+id/text5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="item1" android:layout_toRightOf="@id/img5" android:layout_centerVertical="true" /> </RelativeLayout> </LinearLayout> </RelativeLayout></span></span>
<span style="font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:14px;"><?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" > <googleplay.xiaokai.com.qq.SlidMenu android:id="@+id/horscrview" android:layout_width="wrap_content" android:layout_height="match_parent" android:background="@drawable/img_frame_background" android:scrollbars="none" > <LinearLayout android:layout_width="wrap_content" android:layout_height="match_parent" android:orientation="horizontal" > <include layout="@layout/left_menulayout"/> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/qq" > </LinearLayout> </LinearLayout> </googleplay.xiaokai.com.qq.SlidMenu> </LinearLayout></span> </span>
<span style="font-size:18px;">package googleplay.xiaokai.com.qq; import android.content.Context; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.TypedValue; import android.view.MotionEvent; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.HorizontalScrollView; import android.widget.LinearLayout; /** * Created by 孙晓凯 on 2016/3/27. */ public class SlidMenu extends HorizontalScrollView { int mScreenWit;//屏幕宽度 int mRightWithScr; LinearLayout mWrap; ViewGroup mMenu; ViewGroup mContent; int mMenuWidth ; private boolean flag; public SlidMenu(Context context, AttributeSet attrs) { super(context, attrs); //得到屏幕的宽度 WindowManager winmana = (WindowManager) context.getSystemService(context.WINDOW_SERVICE); DisplayMetrics metris = new DisplayMetrics(); winmana.getDefaultDisplay().getMetrics(metris); mScreenWit = metris.widthPixels;//得到的是像素 //把50dp转换成像素 mRightWithScr = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources().getDisplayMetrics()); } public SlidMenu(Context context) { super(context); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (!flag) { mWrap = (LinearLayout) getChildAt(0);//得到此空间中的第一个子控件 mMenu = (ViewGroup) mWrap.getChildAt(0);//得到menu mContent = (ViewGroup) mWrap.getChildAt(1);//得到内容控件 mMenuWidth = mMenu.getLayoutParams().width = mScreenWit - mRightWithScr;//側滑菜单的宽度为屏幕宽度减去50dp mContent.getLayoutParams().width = mScreenWit;//设置内容控件宽度 flag = true; } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } /* 实现的功能是将menu隐藏,通过设置偏移量 */ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { if(changed) { this.scrollTo(mMenuWidth, 0);//向左移动 } super.onLayout(changed, l, t, r, b); } @Override public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); switch (action){ case MotionEvent.ACTION_UP: int scx = getScrollX(); //就是当前view的左上角相对于母视图的左上角的X轴偏移量 if(scx>=mMenuWidth/2){ this.smoothScrollTo(mMenuWidth,0); }else{ this.smoothScrollTo(0,0); } return true; } return super.onTouchEvent(ev); } }</span>
<span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?
> <resources> <declare-styleable name="SlidMenu"> <attr name="RithtPadding" format="dimension"> </attr> </declare-styleable> </resources> RithtPadding就是自己定义的属性的名称; <?xml version="1.0" encoding="utf-8"?
> <LinearLayout xmlns:my="http://schemas.android.com/apk/res-auto" <!--注意。要使用自己的命名空间--!> xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" > <googleplay.xiaokai.com.qq.SlidMenu android:id="@+id/horscrview" android:layout_width="wrap_content" android:layout_height="match_parent" android:background="@drawable/img_frame_background" android:scrollbars="none" my:RithtPadding="100dp" <!--自己定义的控件--!> > <LinearLayout android:layout_width="wrap_content" android:layout_height="match_parent" android:orientation="horizontal" > <include layout="@layout/left_menulayout"/> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/qq" > </LinearLayout> </LinearLayout> </googleplay.xiaokai.com.qq.SlidMenu> </LinearLayout></span>
<span style="font-size:18px;">public SlidMenu(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //得到屏幕的宽度 WindowManager winmana = (WindowManager) context.getSystemService(context.WINDOW_SERVICE); DisplayMetrics metris = new DisplayMetrics(); winmana.getDefaultDisplay().getMetrics(metris); mScreenWit = metris.widthPixels;//得到的是像素 <span style="color:#3366ff;">TypedArray array = context.getTheme().obtainStyledAttributes(attrs,R.styleable.SlidMenu,defStyleAttr,0); int n = array.getIndexCount(); for(int i=0;i<n;i++){ int attr = array.getIndex(i); switch (attr){ case R.styleable.SlidMenu_RithtPadding: mRightWithScr = array.getDimensionPixelSize(attr,(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources().getDisplayMetrics())); break; } } array.recycle();//</span> }</span>
<span style="font-size:18px;">/* 打开菜单 */ public void openMenu(){ if(isOpen)return; else { this.smoothScrollTo(0,0);//打开 isOpen = true; } } /* 关闭菜单 */ public void closeMenu(){ if(!isOpen){ return ; }else{ this.smoothScrollTo(mMenuWidth,0); isOpen = false; } } /* 切换菜单 */ public void toggle(){ if(isOpen){ closeMenu(); }else{ openMenu(); } }</span>
<span style="font-size:18px;">public class MainActivity extends AppCompatActivity { private SlidMenu slidmenu; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); supportRequestWindowFeature(Window.FEATURE_NO_TITLE);<span style="font-family: Arial, Helvetica, sans-serif;">//</span><span style="font-family: Arial, Helvetica, sans-serif;">假设继承的是ActionBarActivity或者是AppCompatActivity就会报错,</span><span style="font-family: Arial, Helvetica, sans-serif;">假设你执意要用这种方法,请继承Activity。</span> // 假设你继承的是AppCompatActivity或ActionBarActivity请调用以下的方法取代上面的方法 // supportRequestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); slidmenu = (SlidMenu) findViewById(R.id.horscrview); } public void toggle(View view){ slidmenu.toggle(); } } </span>
<span style="font-size:18px;">/** * 滚动发生时 */ @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); /** * 差别1:内容区域1.0~0.7 缩放的效果 scale : 1.0~0.0 0.7 + 0.3 * scale * * 差别2:菜单的偏移量须要改动 * * 差别3:菜单的显示时有缩放以及透明度变化 缩放:0.7 ~1.0 1.0 - scale * 0.3 透明度 0.6 ~ 1.0 * 0.6+ 0.4 * (1- scale) ; * */ float rightScale = 0.7f + 0.3f * scale; float leftScale = 1.0f - scale * 0.3f; float leftAlpha = 0.6f + 0.4f * (1 - scale); // 调用属性动画。设置TranslationX ViewHelper.setTranslationX(mMenu, mMenuWidth * scale * 0.8f); ViewHelper.setScaleX(mMenu, leftScale); ViewHelper.setScaleY(mMenu, leftScale); ViewHelper.setAlpha(mMenu, leftAlpha); // 设置content的缩放的中心点 ViewHelper.setPivotX(mContent, 0); ViewHelper.setPivotY(mContent, mContent.getHeight() / 2); ViewHelper.setScaleX(mContent, rightScale); ViewHelper.setScaleY(mContent, rightScale); }</span>
图:
想要源代码的同学,这是源代码地址:https://github.com/anxiaokai/seslidmenu.git
參考资料:慕课网