QQ侧滑菜单

1.基础知识

1.1HorizontalScrollView是一个 FrameLayout   , 这意味着你只能在它下面放置一个子控件 ,这个子控件可以包含很多数据内容。有可能这个子控件本身就是一个布局控件,可以包含非常多的其他用来展示数据的控件。

继承HorizontalScrollView(水平滑动控件)

需要 重写onMeasure,onLayout , onTouchEvent方法

onMeasure中设置子view的大小和本身的大小

onLayout 需要布局子view和自身的位置

 onTouchEvent 触动处理

1.2.

scrollTo(int x,int y):

如果偏移位置发生了改变,就会给mScrollX和mScrollY赋新值,改变当前位置。

注意:x,y代表的不是坐标点,而是偏移量。

例如:

我要移动view到坐标点(100,100),那么我的偏移量就是(0,,0)  - (100,100) = (-100 ,-100)  ,我就要执行view.scrollTo(-100,-100),达到这个效果。


scrollBy(int x,int y):

从源码中看出,它实际上是调用了scrollTo(mScrollX + x, mScrollY + y);

mScrollX + x和mScrollY + y,即表示在原先偏移的基础上在发生偏移,通俗的说就是相对我们当前位置偏移。

根据父类VIEW里面移动,如果移动到了超出的地方,就不会显示。

查看上文中的示意图你就会知道大概。

2.开发

2.1布局
left_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
 >
    
  <LinearLayout 
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_centerInParent="true" 
      android:orientation="vertical"    
      >
      
      <RelativeLayout
          android:layout_width="fill_parent"
          android:layout_height="wrap_content" 
          >
          <ImageView 
              android:id="@+id/menu_img1"
              android:layout_width="50dp"
              android:layout_height="50dp"
              android:src="@drawable/ic_launcher"
              />
          <TextView 
              android:id="@+id/menu_tv1"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_toRightOf="@id/menu_img1"
              android:text="第一个item"
              android:layout_centerVertical="true"
              />
      </RelativeLayout>
     
      <RelativeLayout
          android:layout_width="fill_parent"
          android:layout_height="wrap_content" 
          >
          <ImageView 
              android:id="@+id/menu_img2"
              android:layout_width="50dp"
              android:layout_height="50dp"
              android:src="@drawable/ic_launcher"
              />
          <TextView 
              android:id="@+id/menu_tv2"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_toRightOf="@id/menu_img2"
              android:text="第2个item"
              android:layout_centerVertical="true"
              />
      </RelativeLayout>
    
      <RelativeLayout
          android:layout_width="fill_parent"
          android:layout_height="wrap_content" 
          >
          <ImageView 
              android:id="@+id/menu_img3"
              android:layout_width="50dp"
              android:layout_height="50dp"
              android:src="@drawable/ic_launcher"
              />
          <TextView 
              android:id="@+id/menu_tv3"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_toRightOf="@id/menu_img3"
              android:text="第3个item"
              android:layout_centerVertical="true"
              />
      </RelativeLayout>
      
      <RelativeLayout
          android:layout_width="fill_parent"
          android:layout_height="wrap_content" 
          >
          <ImageView 
              android:id="@+id/menu_img4"
              android:layout_width="50dp"
              android:layout_height="50dp"
              android:src="@drawable/ic_launcher"
              />
          <TextView 
              android:id="@+id/menu_tv4"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_toRightOf="@id/menu_img4"
              android:text="第4个item"
              android:layout_centerVertical="true"
              />
      </RelativeLayout>
      
      
  </LinearLayout>
    
</RelativeLayout>

main_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
 >
   
    <com.hzs.view.MenuSlidingView 
        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/content"
            >
            </LinearLayout>
            
        </LinearLayout>
        
        
    </com.hzs.view.MenuSlidingView >
  
    
</RelativeLayout>

2.2自定义view
package com.hzs.view;


import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
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 MenuSlidingView extends HorizontalScrollView {


//HorizontalScrollView中只有一个布局
private LinearLayout linearLayout;
//定义左菜单
private ViewGroup mMenu;
//定义内容
private ViewGroup mContent;
//定义频幕宽度
private int mScreenWidth;
//定义menu的宽度
private int mMenuWidth;
//定义menu距离右侧的宽度
private int mMenuRightPadding=50;
private boolean once=false;


public MenuSlidingView(Context context, AttributeSet attrs) {
super(context, attrs);

//获取频幕宽度
 WindowManager wm=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
 DisplayMetrics outMetrics=new DisplayMetrics();
 wm.getDefaultDisplay().getMetrics(outMetrics);
 mScreenWidth=outMetrics.widthPixels;
 //使用TypeValue将dp转换成px
 TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources().getDisplayMetrics());
 
}

/**
* 设置子view的宽和高,设置自己的宽和高
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {


if(!once){
//获取第一个布局元素
linearLayout=(LinearLayout) getChildAt(0);
//获取linerLayout的第一元素
mMenu=(ViewGroup) linearLayout.getChildAt(0);
//获取linerLayout的第一元素
mContent=(ViewGroup) linearLayout.getChildAt(1);

mMenuWidth=mMenu.getLayoutParams().width=mScreenWidth-mMenuRightPadding;
mContent.getLayoutParams().width=mScreenWidth;
once=true;

}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);


}


/**
* 通过设置偏移量,将menu隐藏
*/

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
super.onLayout(changed, l, t, r, b);
        if(changed){
        this.scrollBy(mMenuWidth, 0);
        }


}


@Override
public boolean onTouchEvent(MotionEvent ev) {


        int action=ev.getAction();
        switch (action) {
case MotionEvent.ACTION_UP:

                        //隐藏菜单
int scrollX=getScrollX();
if( scrollX > mMenuWidth / 2 ){
this.smoothScrollTo(mMenuWidth, 0);
}else{
this.smoothScrollTo(0, 0);
}


return true;



}


return super.onTouchEvent(ev);
}

}

  

2.3mainActivity

package com.hzs.view;


import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
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 MenuSlidingView extends HorizontalScrollView {


//HorizontalScrollView中只有一个布局
private LinearLayout linearLayout;
//定义左菜单
private ViewGroup mMenu;
//定义内容
private ViewGroup mContent;
//定义频幕宽度
private int mScreenWidth;
//定义menu的宽度
private int mMenuWidth;
//定义menu距离右侧的宽度
private int mMenuRightPadding=50;
private boolean once=false;


public MenuSlidingView(Context context, AttributeSet attrs) {
super(context, attrs);

//获取频幕宽度
 WindowManager wm=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
 DisplayMetrics outMetrics=new DisplayMetrics();
 wm.getDefaultDisplay().getMetrics(outMetrics);
 mScreenWidth=outMetrics.widthPixels;
 //使用TypeValue将dp转换成px
 TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources().getDisplayMetrics());
 
}

/**
* 设置子view的宽和高,设置自己的宽和高
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {


if(!once){
//获取第一个布局元素
linearLayout=(LinearLayout) getChildAt(0);
//获取linerLayout的第一元素
mMenu=(ViewGroup) linearLayout.getChildAt(0);
//获取linerLayout的第一元素
mContent=(ViewGroup) linearLayout.getChildAt(1);

mMenuWidth=mMenu.getLayoutParams().width=mScreenWidth-mMenuRightPadding;
mContent.getLayoutParams().width=mScreenWidth;
once=true;

}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);


}


/**
* 通过设置偏移量,将menu隐藏
*/

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
super.onLayout(changed, l, t, r, b);
        if(changed){
        this.scrollBy(mMenuWidth, 0);
        }


}


@Override
public boolean onTouchEvent(MotionEvent ev) {


        int action=ev.getAction();
        switch (action) {
case MotionEvent.ACTION_UP:
int scrollX=getScrollX();
if( scrollX > mMenuWidth / 2 ){
this.smoothScrollTo(mMenuWidth, 0);
}else{
this.smoothScrollTo(0, 0);
}


return true;



}


return super.onTouchEvent(ev);
}

}  


猜你喜欢

转载自blog.csdn.net/hzs33/article/details/51887097