1.下载开源SlidingMenu,去Github下载 https://github.com/jfeinstein10/SlidingMenu。
SlidingMenu是一个强大的侧边栏导航框架,自己去codeKK看了源码分析才有了更多的收获 :http://codekk.com/open-source-project-analysis/detail/Android/huxian99/SlidingMenu%20源码解析,这个网站codeKK有许多开源项目的源码解析,是个很不错的学习资源,很感谢这些大牛的奉献。力推这个网站codeKK。
此文章只是自己学习笔记记录,看这个大牛写的,自己加之整理学习了下,感兴趣的看他写的,http://blog.csdn.net/yangyu20121224/article/details/9255829。
1>SlidingMenu功能介绍
SlidingMenu 是一个强大的侧边栏导航框架,主要特点如下:
(1) 侧边栏可以是一个 Fragment,包含任何 View
(2) 使用简单方便,支持左滑和右滑等
(3) 自定义侧边栏显示动画
2>总体设计
SlidingMenu 总体由三个主要的类组成。
(1) SlidingMenu 继承自 RelativeLayout,对外暴露 API 给用户,同时在添加 CustomViewAbove 和。 CustomViewBehind
(2) CustomViewAbove 继承自 ViewGroup,主要用来处理触摸屏事件。
(3) CustomViewBehind 继承自 ViewGroup,主要用来配置参数,显示侧边栏的 Menu 部分。
2.下载SlidingMenu直接导入eclipse,自己再新建Android项目,取名SlidingMenuDemo,之后,右击SlidingMenuDemo-->properties->Android->Add(下面)关联SlidingMenu->Apply->OK,就行,参考下图1. 注意关联后,将SlidingMenuDemo项目中lib下的android-support-v4.jar删除,因为SlidingMenu以及存android-support-v4.jar,否则后面在MainActivity.java会报错。
3. 效果图如下,可以左右滑动,
4.项目类以及布局有关介绍,如下图:
5.具体代码:
1>left_function_fragment.xml 为左侧菜单栏布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:myapp="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#6B6B6B"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/logout_layout"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:gravity="center_horizontal"
android:orientation="vertical" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16.0dip"
android:layout_marginTop="34.0dip"
android:orientation="horizontal" >
<ImageView
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_num2" />
<ImageView
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30.0dip"
android:layout_marginRight="30.0dip"
android:src="@drawable/ic_num4" />
<ImageView
android:id="@+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_num5" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="13.0dip"
android:text="一个吊车尾改变世界的故事"
android:textColor="#ffffff"
android:textSize="11.0sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="#ff272727" />
</LinearLayout>
<ScrollView
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="3" >
<com.example.slidingdemo.MyListView
android:id="@+id/list_itme"
android:layout_width="match_parent"
android:layout_height="200dp" />
</ScrollView>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_marginBottom="10.0dip"
android:layout_marginLeft="19.0dip"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="horizontal" >
<TextView
android:id="@+id/setting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15.0dip"
android:text="设置"
android:textColor="#ffffff"
android:textSize="15.0sp" />
<TextView
android:id="@+id/setting1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15.0dip"
android:text="其他"
android:textColor="#ffffff"
android:textSize="15.0sp" />
</LinearLayout>
</LinearLayout>
2>main_content_frame.xml 为存放右侧菜单内容的Fragment布局
<?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>
3>menu_frame.xml 是用来存放菜单的Fragment
<?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"
>
</FrameLayout>
4>content_item.xml为菜单内容listview的item
<?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 Text111"
android:textColor="@android:color/white"
android:background="@android:color/holo_blue_light"
android:textAppearance="@android:style/TextAppearance.Medium" />
</LinearLayout>
5>list.xml为右边每个菜单内容中的Listview布局
<?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" >
</ListView>
6>menu_item.xml为菜单栏中MyListView中的item
<?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 Text111"
android:textColor="@android:color/white"
android:textAppearance="@android:style/TextAppearance.Medium" />
</LinearLayout>
在values下的dimens.xml添加了这个2个大小属性:
<dimen name="shadow_width">20dp</dimen>
<dimen name="slidingmenu_offset">40dp</dimen>
接着是类
1> MenuListFragment.java是左侧菜单类:
package com.example.slidingdemo;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class MenuListFragment extends Fragment {
private MyListView listview;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view = inflater.inflate(R.layout.left_function_fragment, null);
listview=(MyListView)view.findViewById(R.id.list_itme);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
SampleAdapter adapter = new SampleAdapter(getActivity());
adapter.add(new SampleItem("菜单 List 鸣人", R.drawable.ic_num6));
adapter.add(new SampleItem("菜单 List 佐助", R.drawable.ic_num2));
adapter.add(new SampleItem("菜单 List 卡卡西", R.drawable.ic_num3));
adapter.add(new SampleItem("菜单 List 我爱罗", R.drawable.ic_num7));
adapter.add(new SampleItem("菜单 List 自来也", R.drawable.ic_num4));
adapter.add(new SampleItem("菜单 List 四代", R.drawable.ic_num5));
listview.setAdapter(adapter);
listview.setOnItemClickListener(new OnItemClickListener() {
Fragment newContent=null;
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// TODO Auto-generated method stub
switch (position) {
case 0:
newContent = new MyFragment0();
break;
case 1:
newContent = new MyFragment1();
break;
case 2:
newContent = new MyFragment2();
break;
case 3:
newContent = new MyFragment3();
break;
}
if (newContent != null) {
//切换Fragment
switchFragment(newContent);
}
}
});
}
protected void switchFragment(Fragment newContent) {
// TODO Auto-generated method stub
if (getActivity() == null) {
return;
}
if (getActivity() instanceof MainActivity) {
MainActivity fragChange = (MainActivity) getActivity();
fragChange.switchContent(newContent);
}
}
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.menu_item, 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;
}
}
}
2> MainActivity.java对SlidingMenu进行相关属性配置:
package com.example.slidingdemo;
import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;
import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu.CanvasTransformer;
import com.jeremyfeinstein.slidingmenu.lib.app.SlidingFragmentActivity;
import android.graphics.Canvas;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.animation.Interpolator;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
public class MainActivity extends SlidingFragmentActivity {
private SlidingMenu menu;
private CanvasTransformer transfor;
private Fragment mContent;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_content_frame);
//设置标题
setTitle("客户端");
//设置是否能够使用ActionBar来滑动
setSlidingActionBarEnabled(true);
//设置是否显示Home图标按钮
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setIcon(R.drawable.ic_num1);
//初始化滑动效果
initAnimation();
//初始化滑动菜单
initSlidingMenu(savedInstanceState);
}
/**
* 初始化动画效果
*/
private void initAnimation() {
// TODO Auto-generated method stub
transfor = new CanvasTransformer(){
@Override
public void transformCanvas(Canvas canvas, float percentOpen) {
//canvas画布类;percentOpen:滑动菜单栏打开时的百分比值
// TODO Auto-generated method stub
//以为3种效果,任选一个进行测试
//1.实现滑动时缩放的效果,左边缩下淡去,右边切入屏幕
float scale = (float) (percentOpen*0.25 + 0.75);
canvas.scale(scale, scale, canvas.getWidth()/2, canvas.getHeight()/2);
//2.实现收缩效果
//canvas.scale(percentOpen, 1, 0, 0);
//3.实现菜单栏从下往上滑动效果
// canvas.translate(0, canvas.getHeight() * (1 - interp.getInterpolation(percentOpen)));
}
};
}
private static Interpolator interp = new Interpolator() {
@Override
public float getInterpolation(float t) {
t -= 1.0f;
return t * t * t + 1.0f;
}
};
/**
* 初始化滑动菜单
*/
private void initSlidingMenu(Bundle savedInstanceState) {
// TODO Auto-generated method stub
// 如果保存的状态不为空则得到之前保存的Fragment,否则实例化MyFragment
if(savedInstanceState!=null){
mContent=getSupportFragmentManager().getFragment(savedInstanceState, "mContent");
}
if(mContent==null){
mContent=new MyFragment0();
}
//设置主界面视图
setContentView(R.layout.main_content_frame);
getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, new MyFragment0()).commit();
// 设置滑动菜单的视图界面
setBehindContentView(R.layout.menu_frame);
getSupportFragmentManager().beginTransaction()
.replace(R.id.menu_frame, new MenuListFragment()).commit();
// 设置滑动菜单的属性值
menu=getSlidingMenu();
// 设置触摸屏幕的模式
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.45f);
menu.setBehindScrollScale(0.0f);
menu.setBehindCanvasTransformer(transfor);
}
/*
* 保存Fragment的状态
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
super.onSaveInstanceState(outState);
getSupportFragmentManager().putFragment(outState, "mContent", mContent);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
if(menu.isMenuShowing()){
menu.showContent();
}else{
super.onBackPressed();
}
}
/*
* 菜单按钮点击事件,通过点击ActionBar的Home图标按钮(顶部左边)来打开滑动菜单栏
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case android.R.id.home:
toggle();
return true;
}
return super.onOptionsItemSelected(item);
}
/*
* 切换视图
*/
public void switchContent(Fragment newContent) {
// TODO Auto-generated method stub
mContent = newContent;
getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, newContent).commit();
getSlidingMenu().showContent();
}
}
3>
MyListView
.java重写listview:
package com.example.slidingdemo;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;
/**
* 重写ListView->实现Listview和ScrollView的滚动不冲突
*/
public class MyListView extends ListView {
public MyListView(Context context) {
super(context);
}
public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
4>
MyFragment0
.java是左侧菜单切换对应的内容界面: MyFragment1.java, MyFragment2.java, MyFragment3.java这三个一样,贴出一个代码,测试即可。
package com.example.slidingdemo;
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;
public class MyFragment0 extends ListFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// TODO Auto-generated method stub
return inflater.inflate(R.layout.list, null);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
SampleAdapter adapter = new SampleAdapter(getActivity());
for (int i = 0; i < 30; i++) {
adapter.add(new SampleItem("内容 List 鸣人", R.drawable.ic_left));
}
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.content_item, 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;
}
}
}<span style="font-weight: bold;">
</span>
6.SlidingMenu相关配置属性说明://设置侧边, 必须为 LEFT(左边),RIGHT(右边),LEFT_RIGHT(左右两边)三者之一 public void setMode(int mode)
//设置触摸方式,必须为 TOUCHMODE_FULLSCREEN(全屏可触摸),TOUCHMODE_MARGIN(边缘可触摸),默认 48dp, TOUCHMODE_NONE(不可触摸)三者之一
public void setTouchModeAbove(int i)
// 根据资源文件 ID 设置阴影部分的 width
public void setShadowWidthRes(int resId)
// 根据资源文件 ID 设置阴影部分的效果
public void setShadowDrawable(int resId)
// 根据资源文件 ID 设置第二个侧边栏阴影部分的效果
public void setSecondaryShadowDrawable(int resId)
// 根据资源文件 ID 设置主界面距离屏幕的偏移量
public void setBehindOffsetRes(int resID)
// 设置 fade in 和 fade out 效果的值
public void setFadeDegree(float f)
// 设置滑动比例的值,范围为 0-1 之间
public void setBehindScrollScale(float f)
// 根据资源文件 ID 设置侧边栏布局
public void setMenu(int res)
// 根据 View 设置侧边栏布局
public void setMenu(View v)
// 根据资源文件 ID 设置第二个侧边栏布局
public void setSecondaryMenu(int res)
// 根据 View 设置第二个侧边栏布局
public void setSecondaryMenu(View v)
// 打开菜单
public void showMenu()
// 打开第二个菜单
public void showSecondaryMenu()
// SlidingMenu 的开关
public void toggle()
// 检查侧边栏是否打开
public boolean isMenuShowing()
// 检查第二个侧边栏是否打开
public boolean isSecondaryMenuShowing()