整理自慕课网 实现菜单布局
总体思路:
以HorizontalScrollView为基础。将menu和content从左至右都布局在上面,这样横向的moveEvent就由HorizontalScrollView
代为完成。这样我们就只需要判断横向的偏移量来决定up的时候是显示menu还是content
布局文件就不写了 大致效果就图片上这样
额 还是写一下menu的布局吧
<?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"
android:background="@drawable/img_frame_background">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_centerVertical="true"
android:id="@+id/imag1"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/img_1"
/>
<TextView
android:layout_centerVertical="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:layout_toRightOf="@id/imag1"
android:text="第一个Item"
android:textColor="#ffffff"
android:layout_marginLeft="20dp"
/>
</RelativeLayout>
<多个RelativeLayout/>
</LinearLayout>
</RelativeLayout>
总体布局:自定义的HorizontalScrollView控件,包裹一个横向的ListView,这样当ListView的宽度大于屏幕宽度时,
由于ScrollView的存在就可以实现左右滑动的效果。listView包含一个左边默认隐藏的menu,和右边的一个屏幕大小的content
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns: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="jintong.slidemenu1.MainActivity">
<jintong.slidemenu1.SlidingMenu1
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<include layout="@layout/leftmenu" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/qq">
</LinearLayout>
</LinearLayout>
</jintong.slidemenu1.SlidingMenu1>
</RelativeLayout>
重点:自定义的Horizontal ScrollView;
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;
/**
*
*
* 自定义ViewGroup重点要实现的方法
* 1.onMeasure
* 决定内部View(子View)以及自身的宽和高
* 2.onLayout
* 决定子View的放置的位置
* 3.onTouchEvent
*/
public class SlidingMenu1 extends HorizontalScrollView {
private LinearLayout mWrapper;//包裹菜单和内容
private ViewGroup mMenu;//菜单
private ViewGroup mContent;//内容
private int mScreenWidth;//屏幕宽度
private int mMenuRightPadding;//菜单右侧距离屏幕右侧的距离
private int mMenuWidth;//menu的宽度
//设置一个标记,防止onMeasure多次测量
private boolean once = true;
/**
* 未使用自定义属性时,会调用这个两个参数的构造函数
*/
public SlidingMenu1(Context context, AttributeSet attrs) {
super(context, attrs);
WindowManager wm = (WindowManager) context.getSystemService(context.WINDOW_SERVICE);
//DisplayMetrics经过getMetrics()方法后 ,宽高就被赋值了
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
mScreenWidth = outMetrics.widthPixels;
//把布局使用的dp转为计算时使用的px,padding值是150dp
mMenuRightPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 150, context.getResources().getDisplayMetrics());
}
/**
* 设置子View和自身的宽和高
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//如果是第一次,进行测量,并且在测量设置完成后,once=false
if (once) {
//取出HorizontalScrollView的第一个元素也就是LineaLayout
mWrapper = (LinearLayout) getChildAt(0);
//LineaLayout的第一个元素menu
mMenu = (ViewGroup) mWrapper.getChildAt(0);
mContent = (ViewGroup) mWrapper.getChildAt(1);
//宽度的设置,menu和content的宽度就可以决定wrapper的宽度,就不用设置了
mMenuWidth = mMenu.getLayoutParams().width = mScreenWidth - mMenuRightPadding;
mContent.getLayoutParams().width = mScreenWidth;
once = false;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
/**
* 在不做任何偏移的起始情况下,menu是完全显示的
* 所以要通过设置偏移量,先将menu隐藏
*/
@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);
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_UP:
/**
* 这里的ScrollX表示用户在滑动抬起之后 未拉出的菜单宽度
* 就是仍然隐藏的宽度
* 当这个宽度小于菜单宽度的一半时,应让菜单显示
* 多于菜单的一半时,让菜单继续隐藏
*/
int scrollX = getScrollX();
if (scrollX >= mMenuWidth / 2) {//完全隐藏
this.smoothScrollTo(mMenuWidth, 0);
} else {//完全显示,就是不做偏移的起始位置
this.smoothScrollTo(0, 0);
}
return true;
}
return super.onTouchEvent(ev);
}
}