Android 自定义View修炼-仿QQ5.0 的侧滑菜单效果的实现
有一段时间没有写博客了,最近比较忙,没什么时间写,刚好今天有点时间,
我就分享下,侧滑菜单的实现原理,一般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 的侧滑菜单效果的实现的更多相关文章
- Android 自定义View修炼-仿360手机卫士波浪球进度的实现
像360卫士的波浪球进度的效果,一般最常用的方法就是 画线的方式,先绘sin线或贝塞尔曲线,然后从左到右绘制竖线,然后再裁剪圆区域. 今天我这用图片bitmap的方式,大概的方法原理是: (1)首先用 ...
- Android 自定义View修炼-打造完美的自定义侧滑菜单/侧滑View控件
一.概述 在App中,经常会出现侧滑菜单,侧滑滑出View等效果,虽然说Android有很多第三方开源库,但是实际上 咱们可以自己也写一个自定义的侧滑View控件,其实不难,主要涉及到以下几个要点: ...
- android自定义View之仿通讯录侧边栏滑动,实现A-Z字母检索
我们的手机通讯录一般都有这样的效果,如下图: OK,这种效果大家都见得多了,基本上所有的android手机通讯录都有这样的效果.那我们今天就来看看这个效果该怎么实现. 一.概述 1.页面功能分析 整体 ...
- Android DrawerLayout 高仿QQ5.2双向侧滑菜单
1.概述 之前写了一个Android 高仿 QQ5.0 侧滑菜单效果 自定义控件来袭 ,恰逢QQ5.2又加了一个右侧菜单,刚好看了下DrawerLayout,一方面官方的东西,我都比较感兴趣:另一方面 ...
- Android 自定义View,仿微信视频播放按钮
闲着,尝试实现了新版微信视频播放按钮,使用的是自定义View,先来个简单的效果图...真的很简单哈. 由于暂时用不到,加上时间原因,加上实在是没意思,加上……,本控件就没有实现自定义属性,有兴趣的朋友 ...
- Android 自定义View修炼-Android 实现自定义的卫星式菜单(弧形菜单)View
一.总述 Android 实现卫星式菜单也叫弧形菜单的主要要做的工作如下:1.动画的处理2.自定义ViewGroup来实现卫星式菜单View (1)自定义属性 a. 在attrs.xml中 ...
- Android 自定义View修炼-【2014年最后的分享啦】Android实现自定义刮刮卡效果View
一.简介: 今天是2014年最后一天啦,首先在这里,我祝福大家在新的2015年都一个个的新健康,新收入,新顺利,新如意!!! 上一偏,我介绍了用Xfermode实现自定义圆角和椭圆图片view的博文& ...
- Android 自定义View修炼-自定义View-带百分比进度的圆形进度条(采用自定义属性)
很多的时候,系统自带的View满足不了我们功能的需求,那么我们就需要自己来自定义一个能满足我们需求的View,自定义View我们需要先继承View,添加类的构造方法,重写父类View的一些方法,例如o ...
- Android 自定义View修炼-自定义可动画展开收缩View的实现
有时候需要点击一个view可以动画展开和收缩折叠一个View这样的效果,这样就可以直接自定义View来实现. 本例中,采用继承FrameLayout来实现自定义的ExpandView.下面将详细介绍各 ...
随机推荐
- Hibernate级联操作
cascade属性的可能值有 all: 所有情况下均进行关联操作,即save-update和delete. none: 所有情况下均不进行关联操作.这是默认值. save-update: 在执行sav ...
- 【转】Ubuntu安装基础教程
原文网址:http://teliute.org/linux/Ubsetup/lesson23/lesson23.html 二十三.安装Ubuntu14.04 返回目录 下一课 14.04 版安装与前面 ...
- Loadrunner执行Java脚本
1. Eclipse中调试Java脚本,脚本调试通过后,打成jar包: 2. 新建lr脚本,选择Java vuser协议: 3. Run-time Settings中Classpath设置jar包,没 ...
- 添加iis的wolf、wolf2、json支持
1.打开“mime类型”,添加: 如下“文件扩展名”和“mime类型”: .woff application/x-font-woff .woff2 applic ...
- 【原】Spark on YARN
在YARN上运行Spark 在Spark0.6.0版本开始支持YARN模式,随后的版本在逐渐地完善. 在YARN上启动Spark 确保HADOOP_CONF_DIR或YARN_CONF_DIR属性的值 ...
- 关于FP-Growth 算法一个很好的ppt-学习分享
http://pan.baidu.com/share/link?shareid=1980963149&uk=1594824745
- linux统计文件夹某一些文件的大小总和
du -m smallgame_2006* | awk '{sum += $1}; END{print sum}' -m代表单位是MB, awk命令需要'',且命令需换行
- Installing your app on your Windows RT device
Alright… so my app is almost finished and I want to install it for real on my Surface tablet. How do ...
- java统计程序运行的时间
耗时统计 第一种是以毫秒为单位计算的.long startTime = System.currentTimeMillis(); //获取开始时间 //程序做一些功能性的操作doSomething ...
- 关于IOS中UIWebView 加载HTML内容
NSString *strContent=[info objectForKey:@"newContent"]; { NSArray *paths = NSSearchPathFor ...