使人疲惫的不是远方的高山,而是鞋里的一粒沙子。
本讲内容:滑动菜单
示例一:
下面是res/layout/left_menu.xml 布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/left_menu_bg">
<ListView
android:id="@+id/id_listView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginLeft="20dp"
android:scrollbars="none"/>
</RelativeLayout>
下面是res/layout/left_item.xml 布局文件:
<?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="match_parent" >
<ImageView
android:id="@+id/id_item_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp" />
<TextView
android:id="@+id/id_item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="10dp"
android:textSize="20sp"
android:textColor="#000" />
</LinearLayout>
下面是res/layout/activity_main.xml 布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.q_slidingmenu.SlidingMenu
android:id="@+id/id_menu"
android:layout_width="match_parent"
android:layout_height="match_parent"
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/qq">
<Button
android:onClick="toggleMenu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="切换菜单"/>
</LinearLayout>
</LinearLayout>
</com.example.q_slidingmenu.SlidingMenu>
</RelativeLayout>
下面是SlidingMenu.java主界面文件:
public class SlidingMenu extends HorizontalScrollView {
private LinearLayout mWapper;//整个区域
private ViewGroup mMenu;//左边菜单
private ViewGroup mContent;//内容区域
private int mScreenWidth;//手机屏幕宽度
private int mMenuWidth;//左边菜单宽度
private int mMenuRightPadding=150;//左边菜单距右边屏幕距离 默认单位db
private boolean once;//判断第一次设置子view宽度
private boolean isOpen;//判断是否打开了左边菜单
public SlidingMenu(Context context, AttributeSet attrs) {
super(context, attrs);
//获取屏幕 的宽度
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
mScreenWidth = outMetrics.widthPixels;
//把db转化为px
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources().getDisplayMetrics());
}
/**
* 设置子View的宽和高 设置自己的宽和高
*/
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
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;
}
}
/**
* 通过设置偏移量,将menu隐藏
*/
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if(changed){
this.scrollTo(mMenuWidth, 0);
}
}
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_UP:
int scrollX=getScrollX();//获得隐藏在左边的宽度 getScrollX()获得滑动的x距离(左上角(0,0))
if(scrollX>=mMenuWidth/2){
this.smoothScrollTo(mMenuWidth, 0);//scrollTo 直接定位到对应的位置 而smoothScrollTo是平滑滚动过去的
isOpen=false;
}else{
this.smoothScrollTo(0, 0);
isOpen=true;
}
return true;//注意不是break
}
return super.onTouchEvent(ev);
}
/**
* 打开菜单
*/
public void openMenu(){
if(isOpen){
return;
}else{
this.smoothScrollTo(0, 0);
isOpen=true;
}
}
/**
* 关闭菜单
*/
public void closeMenu(){
if(!isOpen){
return;
}else{
this.smoothScrollTo(mMenuWidth, 0);
isOpen=false;
}
}
/**
* 切换菜单
*/
public void toggle(){
if(isOpen){
closeMenu();
}else{
openMenu();
}
}
}
下面是MainActivity.java主界面文件:
public class MainActivity extends Activity {
private ListView list;
private List<Map<String,Object>> dataList;
private SimpleAdapter adapter;
private SlidingMenu mLeftMenu;
int[] drawable = { R.drawable.setting_icon, R.drawable.camera_icon,R.drawable.add_icon,
R.drawable.photo_icon, R.drawable.qrcode_icon,R.drawable.video_icon };
String[] iconName={"设置","拍照分享","添加好友","我的相册","扫一扫","视频聊天"};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
initViews();
}
private void initViews() {
list=(ListView) findViewById(R.id.id_listView);
dataList=new ArrayList<Map<String,Object>>();
adapter=new SimpleAdapter(this, getData(), R.layout.left_item, new String[]{"image","name"},
new int[]{R.id.id_item_image,R.id.id_item_text});
list.setAdapter(adapter);
mLeftMenu=(SlidingMenu) findViewById(R.id.id_menu);
}
private List<Map<String,Object>> getData(){
for(int i=0;i<drawable.length;i++){
Map<String,Object> map=new HashMap<String,Object>();
map.put("image", drawable[i]);
map.put("name",iconName[i]);
dataList.add(map);
}
return dataList;
}
/**
* 切换菜单
*/
public void toggleMenu(View view){
mLeftMenu.toggle();
}
}
示例二:自定义属性
示例一中每次我们都在原码中修改左边菜单距右边屏幕距离rightPadding太麻烦了,我们可以自定义rightPadding属性
下面是res/values/attrs.xml 文件:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="SlidingMenu"><!-- 告诉系统这是我们自定义的属性 -->
<attr name="rightPadding" format="dimension" /><!-- 自定义属性 -->
</declare-styleable>
</resources>
下面是res/layout/activity_main.xml 布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res/com.example.q_slidingmenu"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.q_slidingmenu.SlidingMenu
android:id="@+id/id_menu"
android:layout_width="match_parent"
android:layout_height="match_parent"
custom:rightPadding="150dp"
android:scrollbars="none">
…………
</RelativeLayout>
一定要引入
xmlns:custom="http://schemas.android.com/apk/res/com.example.customview01"
我们的命名空间,后面的包路径指的是项目的package
下面是SlidingMenu.java主界面文件:
public class SlidingMenu extends HorizontalScrollView {
…………
……
/**
* 当使用自定义控件时默认调用是两个参数的构造方法
* 注意:当我们使用了自定义属性时,要在这里调用三个参数的构造方法,使获取我们自定义的属性
*/
public SlidingMenu(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public SlidingMenu(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// 获取我们定义的属性
TypedArray a=context.getTheme().obtainStyledAttributes(attrs, R.styleable.SlidingMenu, defStyle, 0);
int n=a.getIndexCount();
for(int i=0;i<n;i++){
int attr=a.getIndex(i);
switch (attr) {
case R.styleable.SlidingMenu_rightPadding:
mMenuRightPadding=a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
50,context.getResources().getDisplayMetrics()));//第二个参数是默认值
break;
}
}
a.recycle();//要释放
//获取屏幕 的宽度
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
mScreenWidth = outMetrics.widthPixels;
}
public SlidingMenu(Context context) {
this(context,null);
}
…………
}
示例三:抽屉式菜单
区别:菜单仿佛在内容区域底下
public class SlidingMenu extends HorizontalScrollView {
……
……
/**
* 发生滚动时
* 当 l == oldl , t == oldt 时ScrollView未滑动
*/
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
mMenu.setTranslationX(l);//兼容到3.0
// ViewHelper.setTranslationX(mMenu, l);//导入jar包使兼容到2.0
}
}
示例四:添加动画效果
public class SlidingMenu extends HorizontalScrollView {
…………
/**
* 发生滚动时
* 当 l == oldl , t == oldt 时ScrollView未滑动
*/
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
/**
* 1:内容区域1.0~0.7 缩放的效果 scale : 1.0~0.0 0.7 + 0.3 * scale
* 2:菜单的偏移量需要修改
* 3:菜单的显示时有缩放以及透明度变化 缩放:0.7 ~1.0 1.0 - scale * 0.3 透明度 0.6 ~ 1.0
* 0.6+ 0.4 * (1- scale) ;
*
*/
float scale = l * 1.0f / mMenuWidth;
float rightScale = 0.7f + 0.3f * scale;
float leftScale = 1.0f - scale * 0.3f;
float leftAlpha = 0.6f + 0.4f * (1 - scale);
// 调用属性动画,设置TranslationX
ViewHelper.setTranslationX(mMenu, mMenuWidth * scale * 0.8f);
ViewHelper.setScaleX(mMenu, leftScale);
ViewHelper.setScaleY(mMenu, leftScale);
ViewHelper.setAlpha(mMenu, leftAlpha);
// 设置content的缩放的中心点
ViewHelper.setPivotX(mContent, 0);
ViewHelper.setPivotY(mContent, mContent.getHeight() / 2);
ViewHelper.setScaleX(mContent, rightScale);
ViewHelper.setScaleY(mContent, rightScale);
}
}
注意:内容区域缩放后,顶部会是白色的面板,要把背景设置到activity-main中就可以了