在上一篇文章中,我们介绍了怎么使用DrawerLayout来实现一个简单的侧拉菜单(使用DrawerLayout实现侧拉菜单),也就是我们常说的抽屉效果,GitHub上类似效果的实现方式非常多,实现出来的效果也是非常的绚丽,但是万变不离其宗,Google提供给我们的DrawerLayout才是最基本的,我们今天就来介绍一下怎样通过DrawerLayout来实现QQ5.0的侧拉效果。先来看一张效果图:

好,这是一个我们即将要实现的效果图,关于这个效果,大部分都是很简单的,都是使用了我们在上一篇博客中介绍的DrawerLayout技术来做的,所以如果你还没读过上一篇博客,建议先去看一下DrawerLayout的使用方法(使用DrawerLayout实现侧拉菜单),了解了DrawerLayout的使用方法之后,那么要实现QQ5.0的侧拉效果就如同探囊取物一般。

好了,废话不多说,我们就先来看看怎么实现这样一个效果。

先来看看主布局文件:

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/background" > <RelativeLayout
android:id="@+id/mContent"
android:layout_width="match_parent"
android:layout_height="match_parent" > <ImageView
android:id="@+id/mContent_iv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="0dp"
android:background="@drawable/content_iv"
android:padding="0dp" /> <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:onClick="onClick" />
</RelativeLayout> <fragment
android:id="@+id/left_fragment"
android:name="com.lenve.qqdrawerlayout.LeftMenuFragment"
android:layout_width="220dp"
android:layout_height="match_parent"
android:layout_gravity="left"
android:tag="LEFTMENU" /> </android.support.v4.widget.DrawerLayout>

整个布局文件还是比较简单的,DrawerLayout中一共分为两大块,第一块就是主布局文件,先是是一张图片(这里我直接截了QQ页面的一张图),然后就是一个Button,注意这个Button的位置在整个页面的左上角,Button的背景设置为null,所以我们看不到Button,但是这个Button会响应我们的点击事件,第二部分是一个Fragment,这个Fragment我们看android:layout_gravity="left"属性就知道它是左边菜单栏的Fragment,在上一篇博客中,左边的菜单栏我们并没有使用Fragment,而是直接使用了布局文件,其实这里写成Fragment是比较好的,方便扩展,也方便管理。

好了,既然左边是一个Fragment,我们就来看看这个Fragment长什么样子?

先看看Fragment的布局文件:

<?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" > <ListView
android:id="@+id/left_menu_lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="150dp" >
</ListView> </RelativeLayout>

就一个ListView,够简单吧,再看看listview中item的布局文件:

<?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" > <ImageView
android:id="@+id/left_iv"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginLeft="20dp"
android:padding="12dp"
android:src="@drawable/svip" /> <TextView
android:id="@+id/left_tv"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/left_iv"
android:gravity="center"
android:text="开通会员"
android:textColor="@android:color/white"
android:textSize="14sp" /> </RelativeLayout>

item的布局文件也是比较简单的,左边一个ImageView,右边一个TextView,我们再看看Fragment:

public class LeftMenuFragment extends Fragment {

	private List<LeftMenu> list = null;
private ListView lv; @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initData();
} /**
* 初始化数据
*/
private void initData() {
list = new ArrayList<LeftMenu>();
list.add(new LeftMenu(R.drawable.svip, "开通会员"));
list.add(new LeftMenu(R.drawable.qianbao, "QQ钱包"));
list.add(new LeftMenu(R.drawable.zhuangban, "个性装扮"));
list.add(new LeftMenu(R.drawable.shoucang, "我的收藏"));
list.add(new LeftMenu(R.drawable.xiangce, "我的相册"));
list.add(new LeftMenu(R.drawable.wenjian, "我的文件"));
} @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.left_menu, container, false);
lv = (ListView) view.findViewById(R.id.left_menu_lv);
LeftMenuAdapter adapter = new LeftMenuAdapter(list);
lv.setAdapter(adapter);
return view;
}
}

Fragment整体也是比较简单的,在onCreate方法中拿到模拟数据,然后在onCreateView方法中给listview设置Adapter,在这里我们使用了一个JavaBean,这个JavaBean主要用来存储每一个item中的数据:

public class LeftMenu {

	private int imageView;
private String text; public int getImageView() {
return imageView;
} public void setImageView(int imageView) {
this.imageView = imageView;
} public String getText() {
return text;
} public void setText(String text) {
this.text = text;
} public LeftMenu(int imageView, String text) {
this.imageView = imageView;
this.text = text;
} public LeftMenu() {
} }

在这个JavaBean中,我们存储Image的资源id,然后在使用的时候直接调用这个资源id即可,再看看Adapter:

public class LeftMenuAdapter extends BaseAdapter {

	private List<LeftMenu> list;

	public LeftMenuAdapter(List<LeftMenu> list) {
this.list = list;
} @Override
public int getCount() {
return list.size();
} @Override
public Object getItem(int position) {
return list.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext()).inflate(
R.layout.listview_item, null);
holder = new ViewHolder();
holder.iv = (ImageView) convertView.findViewById(R.id.left_iv);
holder.tv = (TextView) convertView.findViewById(R.id.left_tv);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.iv.setImageResource(list.get(position).getImageView());
holder.tv.setText(list.get(position).getText());
return convertView;
} class ViewHolder {
ImageView iv;
TextView tv;
}
}

这个Adapter很简单,我就不多说了。

nineoldandroids

这些都看完了,就该说说我们的MainActivity,首先我们得大概说说这种效果是怎么实现的,说到这里,我就得给大家介绍一个非常非常出名的动画类了,那就是nineoldandroids,我们在GitHub上可以直接下载到这个动画类的源码(https://github.com/JakeWharton/NineOldAndroids),如果你想用jar包,一会直接下载本项目源码就能拿到了。

nineoldandroids中有一些非常好用的方法,比如:

ViewHelper.setScaleX(View view, float scaleX)
ViewHelper.setScaleY(View view, float scaleY)

通过这个方法,我们可以对一个View进行缩放,第一个参数是我们要缩放的View,第二个参数是缩放比例,还有一个方法:

ViewHelper.setAlpha(View view, float alpha)

通过这个方法,我们可以设置一个View的透明度,第一个参数是我们要改变透明度的View,第二个参数是透明度。还有一个方法:

ViewHelper.setTranslationX(View view, float translationX)

通过这个方法,我们可以对一个View进行平移操作,第一个参数是要平移的View,第二参数是在X轴平移多少。还有一个方法:

ViewHelper.setScaleX(View view, float scaleX)
ViewHelper.setScaleY(View view, float scaleY)

通过这个方法,我们可以设置View变化时的一个轴心。

为什么介绍这几个方法呢?原因很简单,因为我们即将用到。

好了,介绍完这几个方法之后,我们的MainActivity就可以登场了。只需要简单的几个动画我们就可以实现QQ的这种侧拉效果了。

在MainActivity中我们先拿到DrawerLayout的一个实例:

drawerLayout = (DrawerLayout) this.findViewById(R.id.drawerLayout);

然后我们要给DrawerLayout设置一个监听事件,当菜单出场的时候我们调整主布局的位置:

		drawerLayout.setDrawerListener(new DrawerListener() {
@Override
public void onDrawerStateChanged(int newState) {
Log.i("lenve", "onDrawerStateChanged");
} @Override
public void onDrawerSlide(View drawerView, float slideOffset) {
slideAnim(drawerView, slideOffset);
Log.i("lenve", "onDrawerSlide");
} @Override
public void onDrawerOpened(View drawerView) {
Log.i("lenve", "onDrawerOpened");
} @Override
public void onDrawerClosed(View drawerView) {
Log.i("lenve", "onDrawerClosed");
}
});

这个监听事件一共要实现其中的四个方法,看名字我们大概也知道这四个方法是干什么的,那我们看看这四个方法的执行时机:

当我们打开菜单的时候,先执行onDrawerStateChanged,然后不断执行onDrawerSlide,第三步会执行onDrawerOpened,最后执行onDrawerStateChanged,当我们关闭菜单的时候,先执行onDrawerStateChanged,然后不断执行onDrawerSlide,第三步会执行onDrawerClosed,最后执行onDrawerStateChanged,好了,方法的执行时机如果大家还有疑问可以通过打印日志来查看各个方法的执行时机。好了,我们的动画逻辑要在onDrawerSlide方法中来完成,先来说说这个方法的这两个参数,第一个参数是一个View,这个View其实就是左边侧拉菜单的View,第二参数是偏移量,可以简单理解为左边菜单拉出来的比例,它的取值是从0到1。介绍完这个之后,我们来看看slideAnim(drawerView, slideOffset);方法,看看最核心的代码有多么简单:

	private void slideAnim(View drawerView, float slideOffset) {
View contentView = drawerLayout.getChildAt(0);
// slideOffset表示菜单项滑出来的比例,打开菜单时取值为0->1,关闭菜单时取值为1->0
float scale = 1 - slideOffset;
float rightScale = 0.8f + scale * 0.2f;
float leftScale = 1 - 0.3f * scale; ViewHelper.setScaleX(drawerView, leftScale);
ViewHelper.setScaleY(drawerView, leftScale);
ViewHelper.setAlpha(drawerView, 0.6f + 0.4f * (1 - scale));
ViewHelper.setTranslationX(contentView, drawerView.getMeasuredWidth()
* (1 - scale));
ViewHelper.setPivotX(contentView, 0);
ViewHelper.setPivotY(contentView, contentView.getMeasuredHeight() / 2);
contentView.invalidate();
ViewHelper.setScaleX(contentView, rightScale);
ViewHelper.setScaleY(contentView, rightScale);
}

好了,我们可以看到rightScale取值是从1到0.8,那么大家注意rightScale最后用在了contentView上,所以对应的一个显示效果就是contentView从最初大小变为最初大小的0.8倍,leftScale取值是从0.7到1。leftScale最后用在了drawerView,也就是左边的侧拉菜单View,那么对应的显示效果就是左边的菜单View一开始只有原本布局的0.7倍,在菜单慢慢往出滑动的时候,它逐渐变大,直到变为原本的大小(这个时候菜单View已经完全显示出来了)。另外几个动画设置都比较简单,大家参照我们上面对这几个方法的讲解来理解。

好了,搞定这些之后,还剩最后一个东东,就是左上角的点击事件,这个我们在上一篇博客中已经介绍过了,这里我就直接贴代码:

	public void onClick(View v) {
drawerLayout.openDrawer(Gravity.LEFT);
}

所有这些工作做完之后,一个仿QQ5.0侧拉的Demo已经出炉了。。。。

好了,今天就说到这里,大家有什么问题,可以留言讨论。

Demo下载https://github.com/lenve/QQDrawerLayout

使用DrawerLayout实现QQ5.0侧拉菜单效果的更多相关文章

  1. DragLayout: QQ5.0侧拉菜单的新特效

    一.项目概要 1.1 项目效果如图: 1.2 需要使用到的技术   ViewDragHelper: 要实现和QQ5.0侧滑的特效,需要借助谷歌在2013年I/O大会上发布的ViewDragHelper ...

  2. 【转】仿QQ5.0侧滑菜单ResideMenu

    本文由孙国威 原创.如需转载,请注明出处! 原文:http://blog.csdn.net/manoel/article/details/39013095 为了后续对这个项目进行优化,比如透明度动画. ...

  3. 安卓开发笔记——关于开源项目SlidingMenu的使用介绍(仿QQ5.0侧滑菜单)

    记得去年年末的时候写过这个侧滑效果,当时是利用自定义HorizontalScrollView来实现的,效果如下: 有兴趣的朋友可以看看这篇文件<安卓开发笔记——自定义HorizontalScro ...

  4. 仿QQ5.0侧滑菜单

    一.概述 侧滑菜单现在已经非常流行了,目前大概有这么几种:最普通的侧滑,抽屉侧滑,QQ侧滑 注:本文来自慕课网 二.最普通的侧滑 先上图 代码如下: public class MainActivity ...

  5. 仿qq的侧拉菜单效果

    自定义控件 import android.animation.ArgbEvaluator; import android.animation.FloatEvaluator; import androi ...

  6. 使用DrawerLayout实现侧拉菜单

    侧拉菜单在android应用中非常常见,它的实现方式太多了,今天我们就说说使用Google提供的DrawerLayout来实现侧拉菜单效果,先来看张效果图: DrawerLayout的实现其实非常简单 ...

  7. 安卓开发笔记——自定义HorizontalScrollView控件(实现QQ5.0侧滑效果)

    对于滑动菜单栏SlidingMenu,大家应该都不陌生,在市场上的一些APP应用里经常可以见到,比如人人网,FaceBook等. 前段时间QQ5.0版本出来后也采用了这种设计风格:(下面是效果图) 之 ...

  8. Android音乐播放器源码(歌词.均衡器.收藏.qq5.0菜单.通知)

    一款Android音乐播放器源码,基本功能都实现了 qq5.0菜单(歌词.均衡器.收藏.qq5.0菜单.通知) 只有向右滑动出现,菜单键和指定按钮都还没有添加. 源码下载:http://code.66 ...

  9. QQ5.0左侧滑动显示效果

    前三篇为大家介绍了如何实现简单的类QQ5.0左侧的侧滑效果,本篇我将带领大家一起探讨一下如何真正实现QQ5.0左侧的侧滑效果,对于本篇的内容与之前的三篇关联性很强,如果前三篇你已经完全掌握,对于这一篇 ...

随机推荐

  1. CSS选择器一览

    CSS选择器一览 CSS3 选择器 在 CSS 中,选择器是一种模式,用于选择需要添加样式的元素. "CSS" 列指示该属性是在哪个 CSS 版本中定义的.(CSS1.CSS2 还 ...

  2. apache开源项目--Cassandra

    Apache Cassandra是一套开源分布式Key-Value存储系统.它最初由Facebook开发,用于储存特别大的数据.Facebook目前在使用此系统. 主要特性: 分布式 基于column ...

  3. apache开源项目--nutch

    Nutch 是一个开源Java 实现的搜索引擎.它提供了我们运行自己的搜索引擎所需的全部工具.包括全文搜索和Web爬虫. Nutch的创始人是Doug Cutting,他同时也是Lucene.Hado ...

  4. backup archivelog all

     OLTP系统的生产库一般都是打开归档模式,当CUD操作频繁并且时常使用大批量处理时,每天的归档日志也是超级大的,如果长期保留这些归档日志磁盘空间消耗是很恐怖的,所以我们在使用RMAN进行数据库备份时 ...

  5. 嵌入式 uboot、fs、kernel制作和烧录简记-hi3518c

    NULL RAM : mkdir ramdisk_test  临时挂在点 dd if=/dev/zero of=rootfs.ramdisk bs=1k count=10000 建立空硬盘//1500 ...

  6. Android中TextView输入字数统计和限制

    在Android开发应用的时候,文本编辑框中最多输入140个字,经常会显示还剩多少字以限制用户输入的字数, EditText content;//定义一个文本输入框 TextView hasnum;/ ...

  7. OAuth 的权限问题与信息隐忧

    核心提示:以 QQ 登陆和微博登陆为代表的“一键登陆”背后不仅仅是登陆这么简单,它还默认获取了你的其他隐私资料和账号的部分使用权限,我们在享受便利的同时一定不要忘记保护好我们的个人信息安全. 去年3Q ...

  8. 解决SQL数据库无法脱机的问题

    数据库无法脱机:原理——有人在占用. 解决办法: select * from master.sys.sysprocesses where dbid=db_id('数据库名称') kill [id]

  9. hdu 01背包汇总(1171+2546+1864+2955。。。

    1171 题意比较简单,这道题比较特别的地方是01背包中,每个物体有一个价值有一个重量,比较价值最大,重量受限,这道题是价值受限情况下最大,也就值把01背包中的重量也改成价值. //Problem : ...

  10. VisualBox会造成VPN连接不上问题

    今天连接VPN查找点资料,但是怎么也连接不上,一直出现651错误,开始以为是服务器配置原因,重新配置后发现问题依旧,后查找相关资料,发现有提到VisualPC, 感觉VisualBox跟VisualP ...