您的位置:首页 > 其它

使用HorizontalScrollView实现侧滑菜单

2015-04-05 12:42 477 查看
主要继承 HorizontalScrollView 类 ,在构造方法中设置 菜单的宽, 重写 onMeasure, onLayout 方法 ,在 onLayout 中设置初始显示到 内容页的 scrollTo , 一个高级的安卓开发必须熟练掌握 自定义的用法, View的绘制原理。

准备知识:

a. 四舍五入的代码就是把结果加上0.5f再进行强制转换

b. getDimension()是基于当前DisplayMetrics进行转换,获取指定资源id对应的尺寸。文档里并没说这里返回的就是像素,要注意这个函数的返回值是float,像素肯定是int。

getDimensionPixelSize()与getDimension()功能类似,不同的是将结果转换为int,并且小数部分四舍五入。

getDimensionPixelOffset()与getDimension()功能类似,不同的是将结果转换为int,并且偏移转换(offset conversion,函数命名中的offset是这个意思)是直接截断小数位,即取整(其实就是把float强制转化为int,注意不是四舍五入哦)。

1、SlidingMenuView 类的实现如下,

package com.example.slidingmenu;

import com.nineoldandroids.view.ViewHelper;

import android.content.Context;

import android.content.res.TypedArray;

import android.util.AttributeSet;

import android.util.DisplayMetrics;

import android.util.Log;

import android.util.TypedValue;

import android.view.MotionEvent;

import android.view.ViewGroup;

import android.view.WindowManager;

import android.widget.HorizontalScrollView;

import android.widget.LinearLayout;

public class SlidingMenuView extends HorizontalScrollView {

/*

* 1、书写自定义属性的 attr.xml 属性 </br> 2、使用时引入 xmlns命名空间 3、在构造方法中获得我们设置的值

*/

private LinearLayout mWapper;

private ViewGroup mMenu;

private ViewGroup mContent;

private int mScreenWidth;

private int mMenuRightPadding;

private int mMenuWidth;

private boolean hasMeasured = false;

private boolean isOpen = false;

public SlidingMenuView(Context context) {

this(context, null);

}

public SlidingMenuView(Context context, AttributeSet attrs) {

this(context, attrs, -1);

}

/**

* 当使用了 自定义属性时, 会调用 此构造方法

*/

public SlidingMenuView(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

// 获取自定义的属性

TypedArray a = context.getTheme().obtainStyledAttributes(attrs,

R.styleable.SlidingMenu, defStyle, 0);

mMenuRightPadding = a.getDimensionPixelSize(a.getIndex(0),

(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,

100, context.getResources().getDisplayMetrics()));

a.recycle();

WindowManager wm = (WindowManager) context

.getSystemService(context.WINDOW_SERVICE);

DisplayMetrics outMetrics = new DisplayMetrics();

wm.getDefaultDisplay().getMetrics(outMetrics);

mScreenWidth = outMetrics.widthPixels;

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

if (hasMeasured == false) {

mWapper = (LinearLayout) getChildAt(0);

mMenu = (ViewGroup) mWapper.getChildAt(0);

mContent = (ViewGroup) mWapper.getChildAt(1);

mMenuWidth = mMenu.getLayoutParams().width = mScreenWidth

- mMenuRightPadding;

mContent.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);

}

@Override

public boolean onTouchEvent(MotionEvent ev) {

switch (ev.getAction()) {

case MotionEvent.ACTION_UP:

int scrollX = getScrollX(); // 隐藏 在 左边 的 宽度

if (scrollX >= mMenuWidth / 2) {

this.smoothScrollTo(mMenuWidth, 0);

isOpen = false;

} else {

this.smoothScrollTo(0, 0);

isOpen = true;

}

return true;

default:

break;

}

return super.onTouchEvent(ev);

}

@Override

protected void onScrollChanged(int l, int t, int oldl, int oldt) {

super.onScrollChanged(l, t, oldl, oldt);

// 手指滑动时, l 的 值 是 从 mMenuWidth 到 0

Log.e("onScrollChanged", "l="+l + " , oldl="+oldl+ ", mMenuWidth =" +mMenuWidth);

float scaleX = l * 1.0f / mMenuWidth ; // 1.0 ~ 0.0

float contentScale = 0.7f+scaleX*0.3f;

float menuScale = 0.6f + 0.4f *(1- scaleX);

ViewHelper.setTranslationX(mMenu, mMenuWidth * scaleX * 0.95f);

ViewHelper.setPivotX(mMenu, 0);

ViewHelper.setPivotY(mMenu, mContent.getHeight()/2);

ViewHelper.setScaleX(mMenu, menuScale);

ViewHelper.setScaleY(mMenu, menuScale);

ViewHelper.setPivotX(mContent, 0);

ViewHelper.setPivotY(mContent, mContent.getHeight()/2);

ViewHelper.setScaleX(mContent, contentScale);

ViewHelper.setScaleY(mContent, contentScale);

}

public void open() {

if (isOpen == true) {

return;

} else {

this.smoothScrollTo(0, 0);

isOpen = true;

}

}

public void close() {

if (isOpen == true) {

this.smoothScrollTo(mMenuWidth, 0);

isOpen = false;

} else {

return;

}

}

public void toggle(){

if( isOpen )

close();

else

open();

}

}

2、 xml布局文件中使用的方法如下, 注意 HorizontalScrollView 的子布局里只允许有一个根View

<com.example.slidingmenu.SlidingMenuView xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent" >

<LinearLayout

android:layout_width="wrap_content"

android:layout_height="match_parent" >

<include layout="@layout/sliding_menu" />

<LinearLayout

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="#f0f"

android:gravity="center" >

<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="内容页" />

</LinearLayout>

</LinearLayout>

</com.example.slidingmenu.SlidingMenuView>

3、运行效果图





4、 总结



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: