首页 > 代码库 > QQ 5.0侧滑HorizontalScrollView以及自定义ViewGroup

QQ 5.0侧滑HorizontalScrollView以及自定义ViewGroup

  一般侧滑的实现:
       自定义的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确定好之后就确定自己的了)*/@Overrideprotectedvoid 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隐藏*/@Overrideprotectedvoid onLayout(boolean changed,int l,int t,int r,int b){super.onLayout(changed, l, t, r, b);   if(changed){     this.scrollTo(mMenuWidth,0);   }}@Overridepublicboolean 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。
  1. <com.example.kevin.myapplication.SlidingMenuandroid: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属性的集合。
  1. <?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定义命名空间
  1. <com.example.kevin.myapplication.SlidingMenuandroid:id="@+id/id_menu"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/img_frame_background"my:rightPadding="100dp"><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="match_parent"android:orientation="horizontal"><include layout="@layout/left_menu"/><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/qq"><Buttonandroid: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()方法。
  1. //获取定义的属性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。
  1. /**滚动发生时*/@Overrideprotectedvoid 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)。
  1. 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
 
       
 

 

QQ 5.0侧滑HorizontalScrollView以及自定义ViewGroup