滑动菜单

使人疲惫的不是远方的高山,而是鞋里的一粒沙子。


本讲内容:滑动菜单


示例一:

  

下面是res/layout/left_menu.xml 布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/left_menu_bg">
    
    <ListView 
        android:id="@+id/id_listView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_marginLeft="20dp"
        android:scrollbars="none"/>

</RelativeLayout>

下面是res/layout/left_item.xml 布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView
        android:id="@+id/id_item_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="10dp" />

    <TextView
        android:id="@+id/id_item_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:padding="10dp"
        android:textSize="20sp"
        android:textColor="#000" />

</LinearLayout>

下面是res/layout/activity_main.xml 布局文件:

<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" >

    <com.example.q_slidingmenu.SlidingMenu 
        android:id="@+id/id_menu"
        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/left_menu"/>
            
            <LinearLayout 
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@drawable/qq">
                
                <Button 
                    android:onClick="toggleMenu"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                     android:text="切换菜单"/>
                
            </LinearLayout>
        </LinearLayout>
    </com.example.q_slidingmenu.SlidingMenu>

</RelativeLayout>

下面是SlidingMenu.java主界面文件:

public class SlidingMenu extends HorizontalScrollView {
	private LinearLayout mWapper;//整个区域
	private ViewGroup mMenu;//左边菜单
	private ViewGroup mContent;//内容区域
	private int mScreenWidth;//手机屏幕宽度
	
	private int mMenuWidth;//左边菜单宽度
	private int mMenuRightPadding=150;//左边菜单距右边屏幕距离  默认单位db
	
	private boolean once;//判断第一次设置子view宽度
	private boolean isOpen;//判断是否打开了左边菜单

	public SlidingMenu(Context context, AttributeSet attrs) {
		super(context, attrs);
		
		//获取屏幕 的宽度
		WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
		DisplayMetrics outMetrics = new DisplayMetrics();
		wm.getDefaultDisplay().getMetrics(outMetrics);
		mScreenWidth = outMetrics.widthPixels;
		
		//把db转化为px
		TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources().getDisplayMetrics());
	}
	
	/**
	 * 设置子View的宽和高 设置自己的宽和高
	 */
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		if(!once){
			mWapper=(LinearLayout) getChildAt(0);
			mMenu=(ViewGroup) mWapper.getChildAt(0);
			mContent=(ViewGroup) mWapper.getChildAt(1);
			mMenuWidth=mMenu.getLayoutParams().width=mScreenWidth-mMenuRightPadding;
			mContent.getLayoutParams().width=mScreenWidth;
			once=true;
		}
	}
	
	/**
	 * 通过设置偏移量,将menu隐藏
	 */
	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);
		}
	}
	
	public boolean onTouchEvent(MotionEvent ev) {
		switch (ev.getAction()) {
		case MotionEvent.ACTION_UP:
			int scrollX=getScrollX();//获得隐藏在左边的宽度  getScrollX()获得滑动的x距离(左上角(0,0))
			if(scrollX>=mMenuWidth/2){
				this.smoothScrollTo(mMenuWidth, 0);//scrollTo 直接定位到对应的位置 而smoothScrollTo是平滑滚动过去的
				isOpen=false;
			}else{
				this.smoothScrollTo(0, 0);
				isOpen=true;
			}
			return true;//注意不是break
		}
		
		return super.onTouchEvent(ev);
	}
	
	
	/**
	 * 打开菜单
	 */
	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();
		}
	}

}

下面是MainActivity.java主界面文件:

public class MainActivity extends Activity {
	private ListView list;
	private List<Map<String,Object>> dataList;
	private SimpleAdapter adapter;
	
	private SlidingMenu mLeftMenu;
	
	
	int[] drawable = { R.drawable.setting_icon, R.drawable.camera_icon,R.drawable.add_icon,
			R.drawable.photo_icon, R.drawable.qrcode_icon,R.drawable.video_icon };
	String[] iconName={"设置","拍照分享","添加好友","我的相册","扫一扫","视频聊天"};
	
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_main);
		initViews();
	}
	
	private void initViews() {
		list=(ListView) findViewById(R.id.id_listView);
		dataList=new ArrayList<Map<String,Object>>();
		adapter=new SimpleAdapter(this, getData(), R.layout.left_item, new String[]{"image","name"},
				new int[]{R.id.id_item_image,R.id.id_item_text});
		list.setAdapter(adapter);
		
		mLeftMenu=(SlidingMenu) findViewById(R.id.id_menu);
	}
	
	private List<Map<String,Object>> getData(){
		for(int i=0;i<drawable.length;i++){
			Map<String,Object> map=new HashMap<String,Object>();
			map.put("image", drawable[i]);
			map.put("name",iconName[i]);
			dataList.add(map);
		}
		return dataList;
	}
	
	/**
	 * 切换菜单
	 */
	public void toggleMenu(View view){
		mLeftMenu.toggle();
	}
}


示例二:自定义属性

示例一中每次我们都在原码中修改左边菜单距右边屏幕距离rightPadding太麻烦了,我们可以自定义rightPadding属性


下面是res/values/attrs.xml 文件:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="SlidingMenu"><!-- 告诉系统这是我们自定义的属性 -->
        <attr name="rightPadding" format="dimension" /><!-- 自定义属性 -->
    </declare-styleable>

</resources>

下面是res/layout/activity_main.xml 布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res/com.example.q_slidingmenu"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.example.q_slidingmenu.SlidingMenu 
        android:id="@+id/id_menu"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        custom:rightPadding="150dp"
        android:scrollbars="none">
        
        …………
</RelativeLayout>
一定要引入 xmlns:custom="http://schemas.android.com/apk/res/com.example.customview01" 我们的命名空间,后面的包路径指的是项目的package

下面是SlidingMenu.java主界面文件:

public class SlidingMenu extends HorizontalScrollView {
	…………
        ……
	/**
	 * 当使用自定义控件时默认调用是两个参数的构造方法
	 * 注意:当我们使用了自定义属性时,要在这里调用三个参数的构造方法,使获取我们自定义的属性
	 */
	public SlidingMenu(Context context, AttributeSet attrs) {
		this(context, attrs,0);
	}
	
	public SlidingMenu(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		
		// 获取我们定义的属性
		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:
				mMenuRightPadding=a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
						50,context.getResources().getDisplayMetrics()));//第二个参数是默认值
				break;
			}
		}
		a.recycle();//要释放
		
		//获取屏幕 的宽度
		WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
		DisplayMetrics outMetrics = new DisplayMetrics();
		wm.getDefaultDisplay().getMetrics(outMetrics);
		mScreenWidth = outMetrics.widthPixels;
	}

	public SlidingMenu(Context context) {
		this(context,null);
	}
                      …………
}

示例三:抽屉式菜单

区别:菜单仿佛在内容区域底下

public class SlidingMenu extends HorizontalScrollView {
	……
	……
	/**
	 * 发生滚动时
	 * 当 l == oldl , t == oldt 时ScrollView未滑动
	 */
	protected void onScrollChanged(int l, int t, int oldl, int oldt) {
		super.onScrollChanged(l, t, oldl, oldt);
		mMenu.setTranslationX(l);//兼容到3.0
//		ViewHelper.setTranslationX(mMenu, l);//导入jar包使兼容到2.0
	}

}

示例四:添加动画效果

public class SlidingMenu extends HorizontalScrollView {
	…………
	/**
	 * 发生滚动时
	 * 当 l == oldl , t == oldt 时ScrollView未滑动
	 */
	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 scale = l * 1.0f / mMenuWidth;
		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);
	}
}
注意:内容区域缩放后,顶部会是白色的面板,要把背景设置到activity-main中就可以了



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值