一、SlidingMenu简介
相信大家对SlidingMenu都不陌生了,它是一种比较新的设置界面或配置界面的效果,在主界面左滑或者右滑出现设置界面效果,能方便的进行各种操作。很多优秀的应用都采用了这种界面方案,像facebook、人人网、everynote、Google+等等。如下图所示:
Google+界面效果图 everynote界面效果图
因为效果确实比较新颖,所以在很多的应用开发中去实现此效果,解决的办法也是不尽相同。诸多比较以后发
现,还是GitHub上的开源项目SlidingMenu提供了最佳的实现:定制灵活、各种阴影和渐变以及动画的滑动效果都很不错。不过这是一个开源库,而不是一个完整的项目,要把它作为libary引入到你自己的工程里,简单配置一下就可以实现SlidingMenu的效果。
二、SlidingMenu使用
slidingmenu_library下载地址
要想能够实现SlidingMenu的效果,首先必须要将它作为libary导入到你的工程,先看一下它的目录结构,如图:
这里面的代码我就不详细讲解了,主要是教大家怎么直接拿过来用,不过博主对代码进行了一些非常详细的注
释,有兴趣的同学可以好好学习研究一下。
1、下载完毕之后,将此项目导入Eclipse开发环境中,然后执行如下几个步骤:
<1> 点击右键,点击“Import”按钮,弹出对话框选项;
<2> 选中“Existing Projects into Workspace”选项;
<3> 再单击“Browser”按钮后,弹出选项项目对话框,选中要导入的项目;
<4> 点击“Finish”完成。
2、导入项目之后,然后在新建一个Android项目,将slidingmenu_library导入新建的Android项目中,步骤如下:
<1> 右键点击新建的Android项目,然后点击最下方的“Properties”选项;
<2> 点击弹出对话框之后,在最左侧选择“Android”选项,然后再点击右下方的“Add”按钮;
<3> 点击后弹出对话框,选中之前导入的slidingmenu_library项目;
<4> 选中之后如图所示;
<5> 这就说明了导入库已经成功了,导入成功之后会在Android的引用包中出现一个slidingmenu_library.jar包;
注意:这里有个地方需要大家特别注意一下,在新建完Android项目之后,较新的Eclipse版本都会在Android目录下
生成一个libs的文件夹,里面会有一个android-support-v4.jar的jar包,这个jar一定要记得删掉,否则运行程序的时候
会出现异常,提示是找不到类的异常,博主在这个地方纠结了好长时间。最后发现出现异常的原因是因为在导入
slidingmenu_library类库的时候,这个类库里面本身就包含了android-support-v4.jar的jar包,所以运行的时候就会出
现异常,系统不知道去调用哪个路径的下的包,所以程序崩溃,提示找不到类。
通过讲解,相信大家对于开源项目SlidingMenu都有了一个比较初步的了解(不了解的可以参考上
一篇文章),那么从这一章开始,博主将会以SlidingMenu为重心,给大家带来非常丰富的示例演示,让大家对
SlidingMenu有一个更加深入的了解以及如何去实现一些比较炫的滑动效果。
这篇文章会给大家带来7个不同效果的示例,每个示例都包含了最基本的使用方法,从易到难,循序渐进。能够
让初学者可以快速的掌握SlidingMenu的使用方法。下一篇文章会给大家带来三种不同的动画效果来实现滑动菜单栏
的滑动。
关于这些示例,都是SlidingMenu开源项目中自带的一些示例,但是对于初学者来说,要想运行这些示例查看效
果,就必须要导入很多的库,使用起来也是非常的麻烦。博主这里为了能够方便大家更好的学习,就把每个示例都单
独拿了出来,并且添加了一些非常详细的注释,让初学者能够一看就懂,那么博主的目的就达到了。
好的,话不多说,希望大家能够继续支持!
一、示例效果图
先上效果图是博主一贯的作风,这样做可以让大家对于效果的实现有一个大概的了解,可以从中得到自己想要去
实现的效果。
1、示例一效果图
该示例主要是演示通过改变不同的值来改变滑动菜单不同的效果,可以设置的值有:
<1> 设置滑动菜单显示的位置(左边、右边或者左右两边都有);
<2> 设置触摸屏幕的模式(全屏触摸打开滑动菜单、边缘触摸打开滑动菜单或者触摸不能打开滑动菜单);
<3> 设置滑动菜单滑动时缩放的效果以及关闭此效果(值越大效果越明显);
<4> 设置滑动菜单滑动时的阴影效果以及关闭此效果(值越大效果越明显);
<5> 设置滑动菜单滑动时渐入渐出的效果(值越大效果越明显)。
效果图一 效果图二
2、示例二效果图
该示例主要就是教大家实现一个简单的放置在左边滑动菜单栏的效果。
效果图一
3、示例三效果图
该示例实现了在左右两边存放两个视图,并且都可以通滑动屏幕来打开。
4、示例四效果图
该示例主要演示了通过Fragment来改变主视图的界面内容。
5、示例五效果图
该示例也是通过Fragment来改变主视图的界面内容,但不同的是列表中存放的是图片,并且点击列表图片之后会
经过压缩显示出来。
6、示例六效果图
在该示例中使用ViewPager这个类,将多个Fragment存放在viewpager中,并在主界面视图内容中显示出来。
效果图一 效果图二
7、示例七效果图
该示例主要演示了当触摸屏幕滑动时,上面的标题栏TitleBar并不会跟随着一起滑动,滑动的只是中间的内容视图。(印象笔记实现了此效果)
二、代码讲解
由于示例比较多,所以博主我就不对每个示例的代码一一进行讲解了,这里就挑一个最基础的示例给大家讲解一
下。在文章的末尾,我会把所有的示例打包供大家下载学习,里面有一些详细的注释,相信大家能一看就懂。
1、项目结构图
2、content_frame.xml布局
我们先从布局文件开始讲起,这里为什么要定义一个content_frame.xml呢?主要是为了定义一个虚拟的视图,方便Fragment能够替换该视图,以达到Fragment的视图内容能够显示在屏幕上的效果。
[html] view plaincopy
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
大家可以看到这里就定义了一个FrameLayout布局,在给它附上一个id,以至于在系统中可以找到该布局对象。
3、menu_frame.xml布局
这个布局文件是用来存放滑动菜单打开后的视图界面的。
[html] view plaincopy
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/menu_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
4、list.xml
这个list布局文件会在ListFragment中用到。
[html] view plaincopy
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android :id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/list_padding"
android:paddingRight="@dimen/list_padding" />
5、row.xml
用于存放列表中的图片和文本。
[html] view plaincopy
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal" >
<ImageView
android:id="@+id/row_icon"
android:layout_width="50dp"
android:layout_height="50dp"
android:padding="10dp"
android:src="@drawable/ic_launcher" />
<TextView
android:id="@+id/row_title"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:padding="10dp"
android:text="Medium Text"
android:textAppearance="@android :style/TextAppearance.Medium" />
</LinearLayout>
6、shadow.xml资源
这个资源文件是用来实现阴影效果的图形,使用了渐变的绘图效果。
[html] view plaincopy
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<gradient
android:endColor="#33000000"
android:centerColor="#11000000"
android:startColor="#00000000" />
</shape>
7、SampleListFragment类
讲完了布局文件,再让我们来看看Java文件。这个类是用来显示界面中的列表的。
[java] view plaincopy
package com.yangyu.myslidingmenudemo02;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
/**
* @author yangyu
* 功能描述:列表Fragment,用来显示列表视图
*/
public class SampleListFragment extends ListFragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.list, null);
}
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
SampleAdapter adapter = new SampleAdapter(getActivity());
for (int i = 0; i < 20; i++) {
adapter.add(new SampleItem("Sample List", android.R.drawable.ic_menu_search));
}
setListAdapter(adapter);
}
private class SampleItem {
public String tag;
public int iconRes;
public SampleItem(String tag, int iconRes) {
this.tag = tag;
this.iconRes = iconRes;
}
}
public class SampleAdapter extends ArrayAdapter<SampleItem> {
public SampleAdapter(Context context) {
super(context, 0);
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.row, null);
}
ImageView icon = (ImageView) convertView.findViewById(R.id.row_icon);
icon.setImageResource(getItem(position).iconRes);
TextView title = (TextView) convertView.findViewById(R.id.row_title);
title.setText(getItem(position).tag);
return convertView;
}
}
}
8、MainActivity类
这是整个程序的入口类,也是在这个类中,对SlidingMenu的属性进行设置。
[java] view plaincopy
package com.yangyu.myslidingmenudemo02;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;
public class MainActivity extends FragmentActivity {
private SlidingMenu menu;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//设置标题
setTitle("Attach");
//初始化滑动菜单
initSlidingMenu();
}
/**
* 初始化滑动菜单
*/
private void initSlidingMenu() {
// 设置主界面视图
setContentView(R.layout.content_frame);
getSupportFragmentManager().beginTransaction().replace(R.id.content_frame, new SampleListFragment()).commit();
// 设置滑动菜单的属性值
menu = new SlidingMenu(this);
menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
menu.setShadowWidthRes(R.dimen.shadow_width);
menu.setShadowDrawable(R.drawable.shadow);
menu.setBehindOffsetRes(R.dimen.slidingmenu_offset);
menu.setFadeDegree(0.35f);
menu.attachToActivity(this, SlidingMenu.SLIDING_CONTENT);
// 设置滑动菜单的视图界面
menu.setMenu(R.layout.menu_frame);
getSupportFragmentManager().beginTransaction().replace(R.id.menu_frame, new SampleListFragment()).commit();
}
@Override
public void onBackPressed() {
//点击返回键关闭滑动菜单
if (menu.isMenuShowing()) {
menu.showContent();
} else {
super.onBackPressed();
}
}
}
经过上一篇文章的学习,相信大家对开源项目SlidingMenu的用法已经有了一个非常深入的了解,那么这一章博
主就来教大家滑动菜单栏滑动时动画效果的实现。博主这里用了三个不同动画效果的基础示例来教大家如何去实现,
等大家弄懂了之后完全可以做到举一反三,去实现更多不同的动画效果,让你的应用软件给用户带来眼前一亮的
效果。
一、SlidingMenu动画效果示例一
1、示例一效果图
该示例实现了滑动时缩放的效果,看左边的效果图可以明显的感觉到,滑动菜单栏刚刚打开时的图片比右边的效
果图滑动菜单栏打开一大半的图片要小。这里用到的是比例缩放的动画效果。
2、示例一项目结构图
3、示例一代码讲解
关于项目中资源文件的部分我就不详细讲解了,在上篇文章中已经详细的介绍过了,这地方我就着重的讲解一下MainActivity类,也是主程序入口类,滑动菜单栏和滑动的效果都是在此类中实现。
[java] view plaincopy
package com.example.myslidingmenudemo08;
import android.graphics.Canvas;
import android.os.Bundle;
import android.view.MenuItem;
import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;
import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu.CanvasTransformer;
import com.jeremyfeinstein.slidingmenu.lib.app.SlidingFragmentActivity;
public class MainActivity extends SlidingFragmentActivity {
private CanvasTransformer mTransformer;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle("Zoom");
initAnimation();
initSlidingMenu();
getActionBar().setDisplayHomeAsUpEnabled(true);
}
/**
* 初始化滑动菜单
*/
private void initSlidingMenu(){
// 设置主界面视图
setContentView(R.layout.content_frame);
getSupportFragmentManager().beginTransaction().replace(R.id.content_frame, new SampleListFragment()).commit();
// 设置滑动菜单视图
setBehindContentView(R.layout.menu_frame);
getSupportFragmentManager().beginTransaction().replace(R.id.menu_frame, new SampleListFragment()).commit();
// 设置滑动菜单的属性值
SlidingMenu sm = getSlidingMenu();
sm.setShadowWidthRes(R.dimen.shadow_width);
sm.setShadowDrawable(R.drawable.shadow);
sm.setBehindOffsetRes(R.dimen.slidingmenu_offset);
sm.setFadeDegree(0.35f);
sm.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
sm.setBehindScrollScale(0.0f);
sm.setBehindCanvasTransformer(mTransformer);
setSlidingActionBarEnabled(true);
}
/**
* 初始化动画效果
*/
private void initAnimation(){
mTransformer = new CanvasTransformer(){
@Override
public void transformCanvas(Canvas canvas, float percentOpen) {
float scale = (float) (percentOpen*0.25 + 0.75);
canvas.scale(scale, scale, canvas.getWidth()/2, canvas.getHeight()/2);
}
};
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
toggle();
return true;
}
return super.onOptionsItemSelected(item);
}
}
大家可以先看一遍上面的这段代码,要想实现动画效果主要有三个步骤:
<1> 先定义一个CanvasTransformer接口对象,这个接口是在slidingmenu_library类库中封装好的,所以要想运行此项目还要导入slidingmenu_library类库,这个导入的方法已经在前面详细的介绍过了,不清楚的同学可以参考:
[java] view plaincopy
private CanvasTransformer mTransformer;
<2> 然后再实例化此接口,重写接口中的方法:
[java] view plaincopy
mTransformer = new CanvasTransformer(){
@Override
public void transformCanvas(Canvas canvas, float percentOpen) {
float scale = (float) (percentOpen*0.25 + 0.75);
canvas.scale(scale, scale, canvas.getWidth()/2, canvas.getHeight()/2);
}
};
我们可以看到在transformCanvas(Canvas canvas, float percentOpen)方法中,有两个参数:
① Canvas canvas:画布类;
② float percentOpen:滑动菜单栏打开时的百分比值。
<3> 最后在把实例化的接口对象赋给SlidingMenu类中的setBehindCanvasTransformer()方法:
[java] view plaincopy
sm.setBehindCanvasTransformer(mTransformer);
这样,一个滑动菜单栏打开时的动画效果就配置好了,怎么样?还是很简单的吧。
二、SlidingMenu动画效果示例二
1、示例二效果图
该示例主要实现了当滑动菜单栏打开时滑动伸缩的效果,大家通过两站效果图的对比可以很清楚的看到。
2、示例二项目结构图
大家可以拿此图跟示例一的项目结构图做对比,会发现几乎都是一模一样的,不一样的只是MainActivity类中动画
的实现代码不一样,仅此而已。
3、示例二项目代码
MainActivity.java:
[java] view plaincopy
package com.yangyu.myslidingmenudemo09;
import android.graphics.Canvas;
import android.os.Bundle;
import android.view.MenuItem;
import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;
import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu.CanvasTransformer;
import com.jeremyfeinstein.slidingmenu.lib.app.SlidingFragmentActivity;
public class MainActivity extends SlidingFragmentActivity {
private CanvasTransformer mTransformer;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle("Scale");
initAnimation();
initSlidingMenu();
getActionBar().setDisplayHomeAsUpEnabled(true);
}
/**
* 初始化滑动菜单
*/
private void initSlidingMenu(){
// 设置主界面视图
setContentView(R.layout.content_frame);
getSupportFragmentManager().beginTransaction().replace(R.id.content_frame, new SampleListFragment()).commit();
// 设置滑动菜单视图
setBehindContentView(R.layout.menu_frame);
getSupportFragmentManager().beginTransaction().replace(R.id.menu_frame, new SampleListFragment()).commit();
// 设置滑动菜单的属性值
SlidingMenu sm = getSlidingMenu();
sm.setShadowWidthRes(R.dimen.shadow_width);
sm.setShadowDrawable(R.drawable.shadow);
sm.setBehindOffsetRes(R.dimen.slidingmenu_offset);
sm.setFadeDegree(0.35f);
sm.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
sm.setBehindScrollScale(0.0f);
sm.setBehindCanvasTransformer(mTransformer);
setSlidingActionBarEnabled(true);
}
/**
* 初始化动画效果
*/
private void initAnimation(){
mTransformer = new CanvasTransformer(){
@Override
public void transformCanvas(Canvas canvas, float percentOpen) {
canvas.scale(percentOpen, 1, 0, 0);
}
};
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
toggle();
return true;
}
return super.onOptionsItemSelected(item);
}
}
细心的读者会发现,整段代码中跟示例一的代码比起来,只是initAnimation()方法中的代码改变了一点点,正是
因为改变这一点点的代码,就可以实现了滑动伸缩的动画效果。
三、SlidingMenu动画效果示例三
1、示例三效果图
该示例效果实现了当滑动菜单栏刚刚打开时,滑动菜单栏的视图内容从下方渐渐的往上移动,等滑动菜单栏完全
打开时,该视图就会移动到最顶端。大家对比两张效果图就可以很清楚的看到此效果了。
2、示例三项目结构图
3、示例三项目代码
MainActivity.java:
[java] view plaincopy
package com.yangyu.myslidingmenudemo10;
import android.graphics.Canvas;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.animation.Interpolator;
import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;
import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu.CanvasTransformer;
import com.jeremyfeinstein.slidingmenu.lib.app.SlidingFragmentActivity;
public class MainActivity extends SlidingFragmentActivity {
private CanvasTransformer mTransformer;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle("Slide Up");
initAnimation();
initSlidingMenu();
getActionBar().setDisplayHomeAsUpEnabled(true);
}
/**
* 初始化滑动菜单
*/
private void initSlidingMenu(){
// 设置主界面视图
setContentView(R.layout.content_frame);
getSupportFragmentManager().beginTransaction().replace(R.id.content_frame, new SampleListFragment()).commit();
// 设置滑动菜单视图
setBehindContentView(R.layout.menu_frame);
getSupportFragmentManager().beginTransaction().replace(R.id.menu_frame, new SampleListFragment()).commit();
// 设置滑动菜单的属性值
SlidingMenu sm = getSlidingMenu();
sm.setShadowWidthRes(R.dimen.shadow_width);
sm.setShadowDrawable(R.drawable.shadow);
sm.setBehindOffsetRes(R.dimen.slidingmenu_offset);
sm.setFadeDegree(0.35f);
sm.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
sm.setBehindScrollScale(0.0f);
sm.setBehindCanvasTransformer(mTransformer);
setSlidingActionBarEnabled(true);
}
private static Interpolator interp = new Interpolator() {
@Override
public float getInterpolation(float t) {
t -= 1.0f;
return t * t * t + 1.0f;
}
};
/**
* 初始化动画效果
*/
private void initAnimation(){
mTransformer = new CanvasTransformer(){
@Override
public void transformCanvas(Canvas canvas, float percentOpen) {
canvas.translate(0, canvas.getHeight() * (1 - interp.getInterpolation(percentOpen)));
}
};
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
toggle();
return true;
}
return super.onOptionsItemSelected(item);
}
}
在这段代码中,我们将会使用到一个动画插入器Interpolator接口,这个接口是干吗用的呢?
答:在Android的动画效果实现中,我们使用Interpolator来控制动画的进度。Interpolator 定义了动画的变化速度,可以实现匀速、正加速、负加速、无规则变加速等。所以要想实现缓慢往上移动的效果就要使用到此它,并且重写此接口中的getInterpolation(float t)方法。