有一段时间没有写博客了,最近比较忙,没什么时间写,刚好今天有点时间,

我就分享下,侧滑菜单的实现原理,一般android侧滑的实现原理和步骤如下:(源码下载在下面最后给出哈

1.使用ViewGroup 放2个view,一个是menu菜单,一个是content内容

2.监听onTouchEvent事件

处理ACTION_MOVE中的leftMargin位置,从而改变menu菜单的滑动位置

当ACTION_UP时,根据显示菜单的宽度,决定将其显示或隐藏动画效果:

(1)使用Scroller这个辅助类实现动画效果

(2)单起一个Thread(或Task)来改变leftMargin的大小来实现动画效果

上面这种方法,当监听ACTION_MOVE时候,当菜单里有listview等view到时候容易引起手势监听的冲突。

为了避免这种问题,我们采用新的方法来做侧滑。主要是做以下两个处理:

1.不继承ViewGroup,而是继承HorizontalScrollView,这样做的好处是HorizontalScrollView已经帮我们做了相关的监听滑动手势冲突的处理,我们不用操心和处理这些问题。

2.计算Menu菜单的大小,并显示与隐藏menu

3.显示和隐藏menu的动画效果,使用nineoldandroids这个android属性动画开源库。

侧滑菜单的效果截图如下:

      

上面介绍了原理和效果图,下面来看看侧滑菜单类的实现:

1.布局文件的实现:

(1)左侧菜单布局实现:

<?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"
android:background="#00000000" > <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_centerInParent="true"
> <RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" > <TextView
android:id="@+id/menu1"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:gravity="center_vertical"
android:layout_centerVertical="true"
android:textColor="#ffffff"
android:textSize="25sp"
android:text="第一个item1" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" > <TextView
android:id="@+id/menu2"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:gravity="center_vertical"
android:layout_centerVertical="true"
android:textColor="#ffffff"
android:textSize="25sp"
android:text="第二个item2" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" > <TextView
android:id="@+id/menu3"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:gravity="center_vertical"
android:layout_centerVertical="true"
android:textColor="#ffffff"
android:textSize="25sp"
android:text="第三个item3" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" > <TextView
android:id="@+id/menu4"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:gravity="center_vertical"
android:layout_centerVertical="true"
android:textColor="#ffffff"
android:textSize="25sp"
android:text="第四个item4" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" > <TextView
android:id="@+id/menu5"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:gravity="center_vertical"
android:layout_centerVertical="true"
android:textColor="#ffffff"
android:textSize="25sp"
android:text="第五个item5" />
</RelativeLayout>
</LinearLayout> </RelativeLayout>

(2)总布局实现:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
> <com.czm.xcslidemenu.view.XCSlideMenu
android:id="@+id/slideMenu"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/img_frame_background"
android:scrollbars="none" > <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/qihu" > <TextView
android:id="@+id/btnSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/btn_bg"
android:padding="5dp"
android:textSize="16sp"
android:textColor="#FFF"
android:layout_margin="10dp"
android:text="切换菜单" />
</LinearLayout>
</LinearLayout>
</com.czm.xcslidemenu.view.XCSlideMenu> </RelativeLayout>

2.侧滑菜单类的实现:

package com.czm.xcslidemenu.view;

import com.nineoldandroids.view.ViewHelper;

import android.animation.FloatEvaluator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewPropertyAnimator;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.ScaleAnimation;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
/**
* 自定义侧滑菜单View
* @author caizhiming
*
*/
public class XCSlideMenu extends HorizontalScrollView{ private LinearLayout mWapper;
private ViewGroup mMenu;
private ViewGroup mContent;
private int mScreenWidth;
private int mMenuRightPadding;
private int mMenuWidth = 0; private boolean once = false;
//Menu是否处于显示状态
private boolean isSlideOut; public static final int RIGHT_PADDING = 100; public XCSlideMenu(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(metrics);
mScreenWidth = metrics.widthPixels;
//将dp转化为px
mMenuRightPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, XCSlideMenu.RIGHT_PADDING, context.getResources().getDisplayMetrics());
} /**
* 设置子View的宽和高
* 设置自己的宽和高
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
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;
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.scrollTo(mMenuWidth, 0);
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_UP:
//隐藏在左边宽度
int scrollX = getScrollX();
if(scrollX >= mMenuWidth /2){
//Menu 左滑隐藏起来
this.smoothScrollTo(mMenuWidth, 0);
isSlideOut = false;
}else{
//Menu 右滑 显示出来
this.smoothScrollTo(0, 0);
isSlideOut = true;
}
return true;
}
return super.onTouchEvent(ev);
}
/**
* 向右滑出菜单显示出来
*/
public void slideOutMenu(){
if(!isSlideOut){
this.smoothScrollTo(0, 0);
isSlideOut = true;
}else{
return;
}
}
/**
* 向左滑出菜单隐藏起来
*/
public void slideInMenu(){
if(isSlideOut){
this.smoothScrollTo(mMenuWidth, 0);
isSlideOut = false;
}else{
return;
}
}
/**
* 切换菜单向右滑出显示或向左滑出隐藏的状态
*/
public void switchMenu(){
if(isSlideOut){
slideInMenu();
}else{
slideOutMenu();
}
}
/**
* 滚动发生时
*/
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
// TODO Auto-generated method stub
super.onScrollChanged(l, t, oldl, oldt);
//实现抽屉式滑动
float scale = l * 1.0f /mMenuWidth ;//1 ~ 0
float menuScale = 1.0f - scale * 0.3f;
float menuAlpha = 0.0f + 1.0f * (1 - scale);
float contentScale = 0.8f + 0.2f * scale;
//调用属性动画,设置TranslationX
ViewHelper.setTranslationX(mMenu, mMenuWidth*scale*0.8f); //左侧菜单的缩放
ViewHelper.setScaleX(mMenu, menuScale);
ViewHelper.setScaleY(mMenu, menuScale);
//左侧菜单的透明度缩放
ViewHelper.setAlpha(mMenu, menuAlpha); //右侧内容的缩放
ViewHelper.setPivotX(mContent, 0);
ViewHelper.setPivotY(mContent, mContent.getHeight() / 2);
ViewHelper.setScaleY(mContent, contentScale);
ViewHelper.setScaleX(mContent, contentScale);
} }

最后,如何使用该侧滑菜单类呢?很简单,请看下面实例代码:

package com.czm.xcslidemenu;

import com.czm.xcslidemenu.view.XCSlideMenu;

import android.app.Activity;
import android.app.ActionBar;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import android.os.Build; public class MainActivity extends Activity { private XCSlideMenu xcSlideMenu;
private TextView btnSwitch;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
xcSlideMenu = (XCSlideMenu) findViewById(R.id.slideMenu);
btnSwitch = (TextView)findViewById(R.id.btnSwitch);
btnSwitch.setClickable(true);
btnSwitch.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
// TODO Auto-generated method stub
xcSlideMenu.switchMenu();
}
}); } }

最后给出源码的下载:http://download.csdn.net/detail/jczmdeveloper/8286307

真题园网:http://www.zhentiyuan.com

Android 自定义View修炼-仿QQ5.0 的侧滑菜单效果的实现的更多相关文章

  1. Android 自定义View修炼-仿360手机卫士波浪球进度的实现

    像360卫士的波浪球进度的效果,一般最常用的方法就是 画线的方式,先绘sin线或贝塞尔曲线,然后从左到右绘制竖线,然后再裁剪圆区域. 今天我这用图片bitmap的方式,大概的方法原理是: (1)首先用 ...

  2. Android 自定义View修炼-打造完美的自定义侧滑菜单/侧滑View控件

    一.概述 在App中,经常会出现侧滑菜单,侧滑滑出View等效果,虽然说Android有很多第三方开源库,但是实际上 咱们可以自己也写一个自定义的侧滑View控件,其实不难,主要涉及到以下几个要点: ...

  3. android自定义View之仿通讯录侧边栏滑动,实现A-Z字母检索

    我们的手机通讯录一般都有这样的效果,如下图: OK,这种效果大家都见得多了,基本上所有的android手机通讯录都有这样的效果.那我们今天就来看看这个效果该怎么实现. 一.概述 1.页面功能分析 整体 ...

  4. Android DrawerLayout 高仿QQ5.2双向侧滑菜单

    1.概述 之前写了一个Android 高仿 QQ5.0 侧滑菜单效果 自定义控件来袭 ,恰逢QQ5.2又加了一个右侧菜单,刚好看了下DrawerLayout,一方面官方的东西,我都比较感兴趣:另一方面 ...

  5. Android 自定义View,仿微信视频播放按钮

    闲着,尝试实现了新版微信视频播放按钮,使用的是自定义View,先来个简单的效果图...真的很简单哈. 由于暂时用不到,加上时间原因,加上实在是没意思,加上……,本控件就没有实现自定义属性,有兴趣的朋友 ...

  6. Android 自定义View修炼-Android 实现自定义的卫星式菜单(弧形菜单)View

    一.总述 Android 实现卫星式菜单也叫弧形菜单的主要要做的工作如下:1.动画的处理2.自定义ViewGroup来实现卫星式菜单View (1)自定义属性       a. 在attrs.xml中 ...

  7. Android 自定义View修炼-【2014年最后的分享啦】Android实现自定义刮刮卡效果View

    一.简介: 今天是2014年最后一天啦,首先在这里,我祝福大家在新的2015年都一个个的新健康,新收入,新顺利,新如意!!! 上一偏,我介绍了用Xfermode实现自定义圆角和椭圆图片view的博文& ...

  8. Android 自定义View修炼-自定义View-带百分比进度的圆形进度条(采用自定义属性)

    很多的时候,系统自带的View满足不了我们功能的需求,那么我们就需要自己来自定义一个能满足我们需求的View,自定义View我们需要先继承View,添加类的构造方法,重写父类View的一些方法,例如o ...

  9. Android 自定义View修炼-自定义可动画展开收缩View的实现

    有时候需要点击一个view可以动画展开和收缩折叠一个View这样的效果,这样就可以直接自定义View来实现. 本例中,采用继承FrameLayout来实现自定义的ExpandView.下面将详细介绍各 ...

随机推荐

  1. URAL(DP集)

    这几天扫了一下URAL上面简单的DP 第一题 简单递推 1225. Flags #include <iostream> #include<cstdio> #include< ...

  2. cocos2dx 实用小技巧

    Menu 的 是个 很方便的 按钮 c2dx 默认为 MenuItemLabel 添加的 按下 变大 的 动画 却没有 给 MenuItemSprite 提供这样的效果 如果 自己 不想 封装新的 动 ...

  3. bzoj3626

    百度空间马上要下架的说,赶快把最后一点题解补完,然后搬家这是一道不错的题,首先注意询问是满足区间减法的,我们把他变成前缀和表示设我们询问[1,r]中的点和z的LCA深度和,假设我们确定一个根,不难发现 ...

  4. bzoj1670

    第一道凸包 采用Andrew算法,不论实现还是理解都非常简单 ..] of longint;     i,j,k,m,n:longint;     ans:double; procedure swap ...

  5. BZOJ_2002_弹飞绵羊_(LCT)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=2002 一列n个数,a[i]表示向后a[i]个,问第k个数进行多少次向后跳跃会飞出去. 分析 i ...

  6. linq中的contains条件

    linq中的contains条件   在sql查询语句中,in 在linq 中用contains,并且contains前面是数组,而后面是列名,如: SELECT distinct BH FROM c ...

  7. BrnShop开源网上商城第一讲:架构设计

    首先在此感谢大家对BrnShop项目的支持和鼓励!我们在发布BrnShop以前曾推测项目会受到不少园友的支持,但没想到园友们的支持大大超过我们的预测.4天6000次浏览,140个推荐,170个评论,8 ...

  8. python导入模块时的路径疑惑

    有一个事儿,以前没注意,今天发现了,记录一下. 假设一个python文件a.py中,有一段代码,是打印当前路径的.当单独执行a.py文件的时候,打印的是a.py的位置. 但是当a.py文件被其他pyt ...

  9. spoj 1812 LCS2(SAM+DP)

    [题目链接] http://www.spoj.com/problems/LCS2/en/ [题意] 求若干个串的最长公共子串. [思路] SAM+DP 先拿个串建个SAM,然后用后面的串匹配,每次将所 ...

  10. 除去重复记录distinct

    在查询数据库时候,可以使用distinct关键字过滤重复记录 例如 SELECT distinct ShiftID FROM [AdventureWorks].[HumanResources].[Em ...