一般侧滑的实现:
自定义的ViewGroup(menu+content)
ouTouchEvent事件改变ViewGroup的LeftMargin。
大于菜单的一半显示,小于则隐藏(使用Scroller或者LeftMargin加Thread)。
新的方法:
继承HorizontalScrollView,由于menu+content一定是大于屏幕的宽度,那么水平滚动条会自动进行拖动,
我们只要做偏移的距离还显示或隐藏menu或content。
1.最简单的侧滑
自定义ViewGroup即HorizontalScrollView。并复写其中的三个主要方法:
1.onMeasure:即决定内部的View的宽和高,以及自己的宽和高;
2.onLayout:决定子View的放置位置;
3.onTouchEvent:判断用户的状态,控制内部View效果。
scrollTo和scrollBy方法:是scrollView的方法,因为view和Canvas是没有边界的。
public void scrollTo(int x, int y)
说明:在当前视图内容偏移至(x , y)坐标处,即显示(可视)区域位于(x , y)坐标处。
public void scrollBy(int x, int y)
说明:在当前视图内容继续偏移(x , y)个单位,显示(可视)区域也跟着偏移(x,y)个单位。显示部分在大的view中也偏移了位置。
onTouchEvent事件类型:
ACTION_DOWN: 表示用户开始触摸.
ACTION_MOVE: 表示用户在移动(手指或者其他)
ACTION_UP:表示用户抬起了手指
ACTION_CANCEL:表示手势被取消了
publicclassSlidingMenuextendsHorizontalScrollView{ privateLinearLayout mWapper; privateViewGroup mMenu; privateViewGroup mContent; privateint mScreenWidth; privateint mMenuWidth; privateint mMenuRightPadding =50;//menu与屏幕右侧的间距 、 privateboolean once =false; publicSlidingMenu(Context context,AttributeSet attrs){ super(context, attrs); WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics =newDisplayMetrics(); wm.getDefaultDisplay().getMetrics(outMetrics); mScreenWidth = outMetrics.widthPixels; //把dp转换为px mMenuRightPadding =(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,50, context.getResources().getDisplayMetrics()); } /* *设置子view的宽和高,和自己的宽和高(子view确定好之后就确定自己的了) */ @Override protectedvoid 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; //子view宽度决定之后,本身也就决定了 once =true; } } /* *通过设置偏移量,将menu隐藏 */ @Override protectedvoid 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 publicboolean onTouchEvent(MotionEvent ev){ int action = ev.getAction(); switch(action){ caseMotionEvent.ACTION_UP: int scrollX = getScrollX();//scrollX是隐藏是在左边的宽度 if(scrollX >= mMenuWidth/2){ this.smoothScrollTo(mMenuWidth,0); } else{ this.smoothScrollTo(0,0); } returntrue; } returnsuper.onTouchEvent(ev); } }
接着在XML中使用,要使用完整包名,只能放一个子控件,因为是FrameLayout。
-
<com.example.kevin.myapplication.SlidingMenu android:layout_width="match_parent" android:layout_height="match_parent"> <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"> </LinearLayout> </LinearLayout> </com.example.kevin.myapplication.SlidingMenu>
1.1自定义属性
自定义属性:允许用户设置菜单离屏幕右侧属性,常用在view和viewGroup。资源所定义的属性发挥作用取决于自定义组件的代码实现。
1.书写XML文件value/attr.xml;
放在values目录下,属性资源文件的根元素是<resources../>,包含两个元素。
attr子元素:定义一个属性值。
declare-styleable:定义一个styleable对象,每个styleable对象就是一组attr属性的集合。
-
<?xml version="1.0" encoding="utf-8"?> <resources> <attr name="rightPadding" format="dimension"/> <declare-styleable name="SlidingMenu"> <attr name="rightPadding"/> </declare-styleable> </resources>
2.在布局文件进行使用,xmlns定义命名空间。
-
<com.example.kevin.myapplication.SlidingMenu android:id="@+id/id_menu" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/img_frame_background" my:rightPadding="100dp"> <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:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="toggleMenu" android:text="切换菜单"/> </LinearLayout> </LinearLayout> </com.example.kevin.myapplication.SlidingMenu>
更改menu距离右边距离100dp。
3.在构造方法中(3个参数的构造方法)中获得我们设置的值
接着使用TypeArray。它是一个存放恢复obtainStyledAttributes(AttributeSet, int[], int, int)或 obtainAttributes(AttributeSet, int[]) 值的一个
数组容器 。当操作完成以后,一定要调用recycle()方法。
-
//获取定义的属性 TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.SlidingMenu); 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; } }
2.抽屉式侧滑
菜单仿佛在内容区域以下:当左边content拉出多少,左边menu就设置menuWidth-拉出距离的偏移量。
这里需要设置属性动画(3.0引入的):TranslationX。为了往下兼容必须引入com.nineoldandroids:library:2.4.0这个jar。
选择调用动画的时机可用 onScrollChanged。
-
/* *滚动发生时 */ @Override protectedvoid onScrollChanged(int l,int t,int oldl,int oldt){ super.onScrollChanged(l, t, oldl, oldt); float scale = l*1.0f/mMenuWidth;//1~0 //调用属性动画设置anslationX。 ViewHelper.setTranslationX(mMenu, mMenuWidth * scale); }
l相当于就是getScrillX()。
3.QQ式侧滑
区别在于:scale:1~0
1.内容区域缩放1~0.7缩放效果, 0.7+0.3*scale;
2.菜单的偏移量需要修改;
3.菜单的显示有缩放以及透明度0.7~1,1.0 - 0.3*scale。
0.6~1,0.6 + 0.4*(1-scale)。
-
protectedvoid onScrollChanged(int l,int t,int oldl,int oldt){ super.onScrollChanged(l, t, oldl, oldt); float scale = l*1.0f/mMenuWidth;//1~0 //调用属性动画设置anslationX。 ViewHelper.setTranslationX(mMenu, mMenuWidth * scale); float rightScale =0.7f+0.3f* scale; float leftScale =1.0f- scale *0.3f; float leftAlpha =0.6f+0.4f*(1- scale); 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); }
慕课网学习笔记:http://www.imooc.com/learn/211
参考:
http://blog.csdn.net/qinjuning/article/details/7247126 scrollTo 以及 scrollBy方法使用说明
http://blog.csdn.net/qinjuning/article/details/7419207 侧滑实现
http://my.oschina.net/banxi/blog/56421 motionevent