android实现侧滑菜单
2015-07-21 23:52
627 查看
这两天公司比较闲,所以重新研究了一下侧滑菜单。可能是因为很多东西都是现成的吧,基本上都是可以直接拿来就能用的。但是确实感觉自己的技术方面有很多薄弱的地方,都需要去补,所以虽然有现成的框架,还是打算自己实现。
以前有听老师讲过类似的效果,大概的思路是:自定义一个view,横向排列,左边的布局设置margin为负值,加载的时候先隐藏。然后在onTouchListener中,通过移动的x的值来判断是否需要显示左边的菜单。大概是这样,有兴趣的可以自己试试。
不过这两天查看了很多资料后发现,有一种更简单的方式:重写HorizontalScrollView的onMeasure和onLayout,来实现。
public class SlidingMenu extends HorizontalScrollView {
private int ScreenWidth;//屏幕宽度
private int mMenuRightPadding;//菜单离右边的距离
private int mMenuWidth;//菜单的宽度
private TypedArray typedarray;
private int mHalfMenuWidth;
private boolean once=false;
private String TAG="TAG";
public SlidingMenu(Context context) {
super(context);
this.ScreenWidth=getResources().getDisplayMetrics().widthPixels;
}
public SlidingMenu(Context context, AttributeSet attrs) {
super(context, attrs);
this.ScreenWidth=getResources().getDisplayMetrics().widthPixels;//获取手机屏幕宽度
typedarray=context.obtainStyledAttributes(attrs,R.styleable.SlidingMenu);
在SlidingMenu这两个构造方法中,我们都获取了屏幕的宽度。在两个参数的构造方法中,并且我们在两个参数的构造方法中,获取了自定义的属性。
this.ScreenWidth=getResources().getDisplayMetrics().widthPixels;
typedarray=context.obtainStyledAttributes(attrs,R.styleable.SlidingMenu);
mMenuRightPadding=typedarray.getDimensionPixelSize(
R.styleable.SlidingMenu_rightPadding, 50);
/**
*官方的解释是:回收TypedArray,以便后面重用。在调用这个函数后,你就不能再使用这个TypedArray。
*在TypedArray后调用recycle主要是为了缓存。当recycle被调用后,这就说明这个对象从现在可以被重用了。
*TypedArray 内部持有部分数组,它们缓存在Resources类中的静态字段中,这样就不用每次使用前都需要分配内存。
*/
typedarray.recycle(); 然后在onMeasure这个方法中,我们分别拿到根部局的子布局和子布局的子布局,并分别为它们设置了宽度。
然后在onLayout中只做了一件事,就是隐藏菜单栏。
this.scrollTo(mMenuWidth, 0);//隐藏菜单
最后在onTouchEvent中,判断如果在action_up的时候,得到的X坐标值如果大于菜单宽度的一半,就隐藏菜单,反之则显示。这个可能不太好理解,不过自己操作几下应该就能明白。这里需要注意的是,在判断结尾处,必须要加return true,否则会出现菜单隐藏或者出现一半的情况。
case MotionEvent.ACTION_UP:
int upX=getScrollX();
if(upX>mHalfMenuWidth)
{
this.scrollTo(mMenuWidth,0);
}else
{
this.scrollTo(0, 0);
}
return true;参考:http://blog.csdn.net/lmj623565791/article/details/39185641
以前有听老师讲过类似的效果,大概的思路是:自定义一个view,横向排列,左边的布局设置margin为负值,加载的时候先隐藏。然后在onTouchListener中,通过移动的x的值来判断是否需要显示左边的菜单。大概是这样,有兴趣的可以自己试试。
不过这两天查看了很多资料后发现,有一种更简单的方式:重写HorizontalScrollView的onMeasure和onLayout,来实现。
public class SlidingMenu extends HorizontalScrollView {
private int ScreenWidth;//屏幕宽度
private int mMenuRightPadding;//菜单离右边的距离
private int mMenuWidth;//菜单的宽度
private TypedArray typedarray;
private int mHalfMenuWidth;
private boolean once=false;
private String TAG="TAG";
public SlidingMenu(Context context) {
super(context);
this.ScreenWidth=getResources().getDisplayMetrics().widthPixels;
}
public SlidingMenu(Context context, AttributeSet attrs) {
super(context, attrs);
this.ScreenWidth=getResources().getDisplayMetrics().widthPixels;//获取手机屏幕宽度
typedarray=context.obtainStyledAttributes(attrs,R.styleable.SlidingMenu);
//为了不让菜单铺满整个布局,所以设置一个距离。 mMenuRightPadding=typedarray.getDimensionPixelSize( R.styleable.SlidingMenu_rightPadding, 50); /** *官方的解释是:回收TypedArray,以便后面重用。在调用这个函数后,你就不能再使用这个TypedArray。 *在TypedArray后调用recycle主要是为了缓存。当recycle被调用后,这就说明这个对象从现在可以被重用了。 *TypedArray 内部持有部分数组,它们缓存在Resources类中的静态字段中,这样就不用每次使用前都需要分配内存。 */ typedarray.recycle(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); /** * 设置菜单的宽度和内容的宽度 */ Log.i(TAG, "---------onMeasure-------------"); if(!once){ LinearLayout linearlayout=(LinearLayout) this.getChildAt(0); ViewGroup menu=(ViewGroup) linearlayout.getChildAt(0); ViewGroup content=(ViewGroup) linearlayout.getChildAt(1); mMenuWidth=ScreenWidth-mMenuRightPadding; mHalfMenuWidth=mMenuWidth/2; menu.getLayoutParams().width=mMenuWidth; content.getLayoutParams().width=ScreenWidth; } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); Log.i(TAG, "---------onLayout-------------"); if(changed) { this.scrollTo(mMenuWidth, 0); once=true; } } @Override public boolean onTouchEvent(MotionEvent ev) { switch(ev.getAction()) { case MotionEvent.ACTION_UP: int upX=getScrollX(); if(upX>mHalfMenuWidth) { this.scrollTo(mMenuWidth,0); }else { this.scrollTo(0, 0); } return true; } return super.onTouchEvent(ev); } }在我们自定义view的时候,首先肯定是需要实现构造方法的。主要实现一个参数的构造方法和两个参数的构造方法。其中一个参数的构造方法,是我们如果直接在代码中实例化对象的时候需要用到的,两个参数的构造方法,是我们在xml文件中需要用到的。
在SlidingMenu这两个构造方法中,我们都获取了屏幕的宽度。在两个参数的构造方法中,并且我们在两个参数的构造方法中,获取了自定义的属性。
this.ScreenWidth=getResources().getDisplayMetrics().widthPixels;
typedarray=context.obtainStyledAttributes(attrs,R.styleable.SlidingMenu);
mMenuRightPadding=typedarray.getDimensionPixelSize(
R.styleable.SlidingMenu_rightPadding, 50);
/**
*官方的解释是:回收TypedArray,以便后面重用。在调用这个函数后,你就不能再使用这个TypedArray。
*在TypedArray后调用recycle主要是为了缓存。当recycle被调用后,这就说明这个对象从现在可以被重用了。
*TypedArray 内部持有部分数组,它们缓存在Resources类中的静态字段中,这样就不用每次使用前都需要分配内存。
*/
typedarray.recycle(); 然后在onMeasure这个方法中,我们分别拿到根部局的子布局和子布局的子布局,并分别为它们设置了宽度。
然后在onLayout中只做了一件事,就是隐藏菜单栏。
this.scrollTo(mMenuWidth, 0);//隐藏菜单
最后在onTouchEvent中,判断如果在action_up的时候,得到的X坐标值如果大于菜单宽度的一半,就隐藏菜单,反之则显示。这个可能不太好理解,不过自己操作几下应该就能明白。这里需要注意的是,在判断结尾处,必须要加return true,否则会出现菜单隐藏或者出现一半的情况。
case MotionEvent.ACTION_UP:
int upX=getScrollX();
if(upX>mHalfMenuWidth)
{
this.scrollTo(mMenuWidth,0);
}else
{
this.scrollTo(0, 0);
}
return true;参考:http://blog.csdn.net/lmj623565791/article/details/39185641
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories