使用DrawerLayout实现QQ5.0侧拉菜单效果
在上一篇文章中,我们介绍了怎么使用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侧拉菜单效果的更多相关文章
- DragLayout: QQ5.0侧拉菜单的新特效
一.项目概要 1.1 项目效果如图: 1.2 需要使用到的技术 ViewDragHelper: 要实现和QQ5.0侧滑的特效,需要借助谷歌在2013年I/O大会上发布的ViewDragHelper ...
- 【转】仿QQ5.0侧滑菜单ResideMenu
本文由孙国威 原创.如需转载,请注明出处! 原文:http://blog.csdn.net/manoel/article/details/39013095 为了后续对这个项目进行优化,比如透明度动画. ...
- 安卓开发笔记——关于开源项目SlidingMenu的使用介绍(仿QQ5.0侧滑菜单)
记得去年年末的时候写过这个侧滑效果,当时是利用自定义HorizontalScrollView来实现的,效果如下: 有兴趣的朋友可以看看这篇文件<安卓开发笔记——自定义HorizontalScro ...
- 仿QQ5.0侧滑菜单
一.概述 侧滑菜单现在已经非常流行了,目前大概有这么几种:最普通的侧滑,抽屉侧滑,QQ侧滑 注:本文来自慕课网 二.最普通的侧滑 先上图 代码如下: public class MainActivity ...
- 仿qq的侧拉菜单效果
自定义控件 import android.animation.ArgbEvaluator; import android.animation.FloatEvaluator; import androi ...
- 使用DrawerLayout实现侧拉菜单
侧拉菜单在android应用中非常常见,它的实现方式太多了,今天我们就说说使用Google提供的DrawerLayout来实现侧拉菜单效果,先来看张效果图: DrawerLayout的实现其实非常简单 ...
- 安卓开发笔记——自定义HorizontalScrollView控件(实现QQ5.0侧滑效果)
对于滑动菜单栏SlidingMenu,大家应该都不陌生,在市场上的一些APP应用里经常可以见到,比如人人网,FaceBook等. 前段时间QQ5.0版本出来后也采用了这种设计风格:(下面是效果图) 之 ...
- Android音乐播放器源码(歌词.均衡器.收藏.qq5.0菜单.通知)
一款Android音乐播放器源码,基本功能都实现了 qq5.0菜单(歌词.均衡器.收藏.qq5.0菜单.通知) 只有向右滑动出现,菜单键和指定按钮都还没有添加. 源码下载:http://code.66 ...
- QQ5.0左侧滑动显示效果
前三篇为大家介绍了如何实现简单的类QQ5.0左侧的侧滑效果,本篇我将带领大家一起探讨一下如何真正实现QQ5.0左侧的侧滑效果,对于本篇的内容与之前的三篇关联性很强,如果前三篇你已经完全掌握,对于这一篇 ...
随机推荐
- 【HDOJ】4455 Substrings
5000ms的时限,还挺长的.算法是DP.思路是找到ans[1..n]的结果,然后Query就容易做了.问题是怎么DP?考虑:1 1 2 3 4 4 5w=1: 7, 7 = 1 * 7w=2: 10 ...
- BZOJ_1008_[HNOI2008]_越狱_(简单组合数学+快速幂)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1008 监狱有连续编号为1...N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰 ...
- [转] acmer必看的26个对acm态度
acmer必看的26个对acm态度 转载自:http://www.cppblog.com/Darren/archive/2009/08/03/92099.html Attempt Keep on ...
- jquery easyui treegrid使用小结
在实际应用中可能会碰到不同的需求,比如会根据每行不同的参数或属性设置来设置同列不同的editor类型,这时原有的例子就显的有点太过简单,不能实现我们的需求,现在应用我在项目中的操作为例,显示下实现同列 ...
- mac book air 装win7
1. 使用mac book air A1465中 bootCamp制作启动U盘: 需要U盘一个8G,windows 7 原版镜像ISO安装文件一个,根据bootcamp操作提示选择文件及U盘, 注意U ...
- 【转】关于usr/bin/ld: cannot find -lxxx问题总结
原文网址:http://eminzhang.blog.51cto.com/5292425/1285705 /usr/bin/ld: cannot find -lxxx问题总结 linux下编译应用 ...
- HTMLPARSER.NET 参考资料
例子1: using System;using System.IO;using Winista.Text.HtmlParser;using Winista.Text.HtmlParser.Lex;us ...
- lightoj 1013
思路:动态规划.设dp[i][j][k]表示用第一个串的前i隔字符和第二个串的前k隔字符组成长度为i的串的个数,那么:若s1[j+1] == s2[k+1] dp[i+1][j+1][k+1] += ...
- loadrunner SQL2008
1. 下载 JDBC 驱动(sqljdbc4.jar) 2. 在 run-time setting 下的 classpath 把 JDBC 驱动引入 /* * LoadRunner Java scri ...
- getchar
getchar函数每次只从缓冲区中接受一个字符. getchar有一个int型的返回值. 当程序调用getchar时,程序就等着用户按键,用户输入的字符被存放在键盘缓冲区中,直到用户按回车为止(回车字 ...