码迷,mamicode.com
首页 > 其他好文 > 详细

QQ 5.0侧滑HorizontalScrollView以及自定义ViewGroup

时间:2015-01-18 18:32:29      阅读:336      评论:0      收藏:0      [点我收藏+]

标签:

  一般侧滑的实现:
       自定义的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。
  1. <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属性的集合。
  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.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()方法。
  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. /*
    *滚动发生时
    */
    @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)。
  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://my.oschina.net/banxi/blog/56421                        motionevent
 
       
 

 

QQ 5.0侧滑HorizontalScrollView以及自定义ViewGroup

标签:

原文地址:http://www.cnblogs.com/fruitbolgs/p/4232002.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!