1. 一般侧滑的实现
ViewGroup Menu + Content
onTouchEvent
MOVE: ViewGroup的leftMargin
UP:根据现实菜单的宽度,决定将其隐藏或者显示
自定义ViewGroup
onMesure 决定内部View(子View)的宽和高,决定自己的宽和高
onLayout 决定子View 放置的位置
onTouchEvent 判断状态来移动效果
抽屉式侧滑
区别:菜单仿佛在内容区域底下
mMenuWidth
100dp mMenuWidth - 100
200dp mMenuWidth - 200
属性动画(Android 3.0) :TranslationX
getScroll:mMenuWidth ~ 0 //显示过程
调用动画时机:ACTION_MOVE
区别1:内容区域1.0~0.7缩放的效果
scale:1.0~0.0
0.7 + 0.3 * scale
区别2:菜单的偏移量需要修改
区别3:菜单的显示时有缩放,以及透明度变化
缩放:0.7 ~ 1.0
1.0 - scale * 0.3
透明度0.6 ~ 1.0
0.6 + 0.4 * (1 - scale
动画:点击下载jar包
package com.zzc.view;
import com.example.message.R;
import com.nineoldandroids.view.ViewHelper;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.MonthDisplayHelper;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.TranslateAnimation;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
public class SlidingMenu extends HorizontalScrollView {
private LinearLayout mWapper;// HorizontalScrollView下唯
private ViewGroup mMenu;// 菜单
private ViewGroup mContent;// 内容
private int mScreenWidth;// 屏幕宽度
private int mMenuRightPadding = 50;
private int mMenuWdith;// 菜单宽度
private boolean isOpen;// 是否已经打开
private boolean once;// 用来保证单次执行onMeasure方法
public SlidingMenu(Context context) {
this(context, null);
}
/**
* 未使用自定义属性时调用
*
* @param context
* @param attrs
*/
public SlidingMenu(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
/**
* 使用自定义属性时调用此构造方法
*
* @param context
* @param attrs
* @param defStyle
*/
public SlidingMenu(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.SlidingMenu, defStyle, 0);
init(context, a);
}
/**
* 初始化菜单离
* @param context
* @param a
*/
private void init(Context context, TypedArray a) {
// 获取数量用来遍历
int n = a.getIndexCount();
for (int i = 0; i < n; i++) {
int attr = a.getIndex(i);
switch (attr) {
case R.styleable.SlidingMenu_rightPadding:
//用来获取设置的值 默认值为50dp
mMenuRightPadding = a.getDimensionPixelSize(attr,
(int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 50, context
.getResources().getDisplayMetrics()));
break;
}
}
a.recycle();
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
mScreenWidth = outMetrics.widthPixels;
// 把dp转换为px
// mMenuRightPadding = (int) TypedValue.applyDimension(
// TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources()
// .getDisplayMetrics());
}
/**
* 设置子View的宽和高 ,自己的宽和高
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (!once) {
mWapper = (LinearLayout) getChildAt(0);
mMenu = (ViewGroup) mWapper.getChildAt(0);
mContent = (ViewGroup) mWapper.getChildAt(1);
// 菜单的宽度
mMenuWdith = 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) {
super.onLayout(changed, l, t, r, b);
if (changed) {
// 默认隐藏menu
this.scrollTo(mMenuWdith, 0);
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
//如果显示区域大于菜单宽度一半则完全显示,否则隐藏
case MotionEvent.ACTION_UP:
// 内容的0起点 到menu右边缘的x值 用来判断抬起时menu是否隐藏
int scrllX = getScrollX();
if (scrllX >= mMenuWdith / 2) {
//scrollTo是瞬间完成 smoothScrollTo内部有动画效果
this.smoothScrollTo(mMenuWdith, 0);
isOpen = false;//隐藏
} else {
this.smoothScrollTo(0, 0);
isOpen = true;//显示
}
return true;
}
return super.onTouchEvent(ev);
}
/**
* 打开菜单
*/
public void openMenu(){
if(isOpen)return;
this.smoothScrollTo(0, 0);
isOpen = true;
}
/**
* 关闭菜单
*/
public void closeMenu(){
if(!isOpen)return;
this.smoothScrollTo(mMenuWdith, 0);
isOpen = false;
}
/**
* 切换菜单
*/
public void toggle(){
if(isOpen){
closeMenu();
}else{
openMenu();
}
}
/**
* scale:1.0~0.0
0.7 + 0.3 * scale
区别2:菜单的偏移量需要修改
区别3:菜单的显示时有缩放,以及透明度变化
缩放:0.7 ~ 1.0
1.0 - scale * 0.3
透明度0.6 ~ 1.0
0.6 + 0.4 * (1 - scale);
*/
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
float scale = l * 1.0f/mMenuWdith;//1 ~ 0
float rightScale = 0.7f + 0.3f * scale;
float leftScale = 1.0f - scale * 0.3f;
float leftAlpha = 0.6f + 0.4f * (1 - scale);
//调用属性动画,设置TranslationX 用的nineoldandroids为了保持向下的兼容
ViewHelper.setTranslationX(mMenu, mMenuWdith * scale * 0.8f);
//设置menu缩放
ViewHelper.setScaleX(mMenu, leftScale);
ViewHelper.setScaleY(mMenu, leftScale);
//设置menu透明度变化
ViewHelper.setAlpha(mMenu, leftAlpha);
//设置mContent缩放的中心点
ViewHelper.setPivotX(mContent, 0);
ViewHelper.setPivotY(mContent,mContent.getHeight()/2);
//设置mContent缩放
ViewHelper.setScaleX(mContent, rightScale);
ViewHelper.setScaleY(mContent, rightScale);
}
}
2.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/id_img1"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@drawable/ic_launcher" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/id_img1"
android:text="第一个item"
android:textSize="20sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/id_img2"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@drawable/ic_launcher" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/id_img2"
android:text="第二个item"
android:textSize="20sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/id_img3"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@drawable/ic_launcher" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/id_img3"
android:text="第三个item"
android:textSize="20sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/id_img4"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@drawable/ic_launcher" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/id_img4"
android:text="第四个item"
android:textSize="20sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/id_img5"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@drawable/ic_launcher" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/id_img5"
android:text="第五个item"
android:textSize="20sp" />
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
3.加载SlidingMenu
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:menu="http://schemas.android.com/apk/res/com.example.message"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.zzc.view.SlidingMenu
android:id="@+id/sliding_menu"
android:layout_width="match_parent"
android:layout_height="match_parent"
menu:rightPadding="60dp" >
<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/bb" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="切换"
android:onClick="toogle"/>
</LinearLayout>
</LinearLayout>
</com.zzc.view.SlidingMenu>
</RelativeLayout>
自定义ViewGroup
onMesure 决定内部View(子View)的宽和高,决定自己的宽和高
onLayout 决定子View 放置的位置
onTouchEvent 判断状态来移动效果
抽屉式侧滑
区别:菜单仿佛在内容区域底下
mMenuWidth
100dp mMenuWidth - 100
200dp mMenuWidth - 200
属性动画(Android 3.0) :TranslationX
getScroll:mMenuWidth ~ 0 //显示过程
调用动画时机:ACTION_MOVE
区别1:内容区域1.0~0.7缩放的效果
scale:1.0~0.0
0.7 + 0.3 * scale
区别2:菜单的偏移量需要修改
区别3:菜单的显示时有缩放,以及透明度变化
缩放:0.7 ~ 1.0
1.0 - scale * 0.3
透明度0.6 ~ 1.0
0.6 + 0.4 * (1 - scale
动画:点击下载jar包
package com.zzc.view;
import com.example.message.R;
import com.nineoldandroids.view.ViewHelper;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.MonthDisplayHelper;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.TranslateAnimation;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
public class SlidingMenu extends HorizontalScrollView {
private LinearLayout mWapper;// HorizontalScrollView下唯
private ViewGroup mMenu;// 菜单
private ViewGroup mContent;// 内容
private int mScreenWidth;// 屏幕宽度
private int mMenuRightPadding = 50;
private int mMenuWdith;// 菜单宽度
private boolean isOpen;// 是否已经打开
private boolean once;// 用来保证单次执行onMeasure方法
public SlidingMenu(Context context) {
this(context, null);
}
/**
* 未使用自定义属性时调用
*
* @param context
* @param attrs
*/
public SlidingMenu(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
/**
* 使用自定义属性时调用此构造方法
*
* @param context
* @param attrs
* @param defStyle
*/
public SlidingMenu(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.SlidingMenu, defStyle, 0);
init(context, a);
}
/**
* 初始化菜单离
* @param context
* @param a
*/
private void init(Context context, TypedArray a) {
// 获取数量用来遍历
int n = a.getIndexCount();
for (int i = 0; i < n; i++) {
int attr = a.getIndex(i);
switch (attr) {
case R.styleable.SlidingMenu_rightPadding:
//用来获取设置的值 默认值为50dp
mMenuRightPadding = a.getDimensionPixelSize(attr,
(int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 50, context
.getResources().getDisplayMetrics()));
break;
}
}
a.recycle();
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
mScreenWidth = outMetrics.widthPixels;
// 把dp转换为px
// mMenuRightPadding = (int) TypedValue.applyDimension(
// TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources()
// .getDisplayMetrics());
}
/**
* 设置子View的宽和高 ,自己的宽和高
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (!once) {
mWapper = (LinearLayout) getChildAt(0);
mMenu = (ViewGroup) mWapper.getChildAt(0);
mContent = (ViewGroup) mWapper.getChildAt(1);
// 菜单的宽度
mMenuWdith = 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) {
super.onLayout(changed, l, t, r, b);
if (changed) {
// 默认隐藏menu
this.scrollTo(mMenuWdith, 0);
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
//如果显示区域大于菜单宽度一半则完全显示,否则隐藏
case MotionEvent.ACTION_UP:
// 内容的0起点 到menu右边缘的x值 用来判断抬起时menu是否隐藏
int scrllX = getScrollX();
if (scrllX >= mMenuWdith / 2) {
//scrollTo是瞬间完成 smoothScrollTo内部有动画效果
this.smoothScrollTo(mMenuWdith, 0);
isOpen = false;//隐藏
} else {
this.smoothScrollTo(0, 0);
isOpen = true;//显示
}
return true;
}
return super.onTouchEvent(ev);
}
/**
* 打开菜单
*/
public void openMenu(){
if(isOpen)return;
this.smoothScrollTo(0, 0);
isOpen = true;
}
/**
* 关闭菜单
*/
public void closeMenu(){
if(!isOpen)return;
this.smoothScrollTo(mMenuWdith, 0);
isOpen = false;
}
/**
* 切换菜单
*/
public void toggle(){
if(isOpen){
closeMenu();
}else{
openMenu();
}
}
/**
* scale:1.0~0.0
0.7 + 0.3 * scale
区别2:菜单的偏移量需要修改
区别3:菜单的显示时有缩放,以及透明度变化
缩放:0.7 ~ 1.0
1.0 - scale * 0.3
透明度0.6 ~ 1.0
0.6 + 0.4 * (1 - scale);
*/
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
float scale = l * 1.0f/mMenuWdith;//1 ~ 0
float rightScale = 0.7f + 0.3f * scale;
float leftScale = 1.0f - scale * 0.3f;
float leftAlpha = 0.6f + 0.4f * (1 - scale);
//调用属性动画,设置TranslationX 用的nineoldandroids为了保持向下的兼容
ViewHelper.setTranslationX(mMenu, mMenuWdith * scale * 0.8f);
//设置menu缩放
ViewHelper.setScaleX(mMenu, leftScale);
ViewHelper.setScaleY(mMenu, leftScale);
//设置menu透明度变化
ViewHelper.setAlpha(mMenu, leftAlpha);
//设置mContent缩放的中心点
ViewHelper.setPivotX(mContent, 0);
ViewHelper.setPivotY(mContent,mContent.getHeight()/2);
//设置mContent缩放
ViewHelper.setScaleX(mContent, rightScale);
ViewHelper.setScaleY(mContent, rightScale);
}
}
<?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/id_img1"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@drawable/ic_launcher" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/id_img1"
android:text="第一个item"
android:textSize="20sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/id_img2"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@drawable/ic_launcher" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/id_img2"
android:text="第二个item"
android:textSize="20sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/id_img3"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@drawable/ic_launcher" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/id_img3"
android:text="第三个item"
android:textSize="20sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/id_img4"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@drawable/ic_launcher" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/id_img4"
android:text="第四个item"
android:textSize="20sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/id_img5"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@drawable/ic_launcher" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/id_img5"
android:text="第五个item"
android:textSize="20sp" />
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
3.加载SlidingMenu
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:menu="http://schemas.android.com/apk/res/com.example.message"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.zzc.view.SlidingMenu
android:id="@+id/sliding_menu"
android:layout_width="match_parent"
android:layout_height="match_parent"
menu:rightPadding="60dp" >
<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/bb" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="切换"
android:onClick="toogle"/>
</LinearLayout>
</LinearLayout>
</com.zzc.view.SlidingMenu>
</RelativeLayout>