您的位置:首页 > 移动开发 > Android开发

Android自定义侧滑菜单简单示例

2016-08-10 21:35 357 查看

Android自定义侧滑菜单简单示例

本次内容涉及到以下几点:

1.自定义属性TypedArray。这里简单讲下,有时Android自带的控件及属性不能满足我们的需求,则我们就会想到自定义属性。当我们用到TypedArray时,首先要在res/values下建立一个attr.xml。而且若在xml使用该属性,则要定义xml命名空间,然后使用其属性。xmlns=”http://schemas.android.com/apk/res/”+R文件所在的包名,记住一定是R文件所在的包名

如attr.xml内容如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="rightPadding" format="dimension" />
</resources>


则我们在main.xml使用:

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"                xmlns:yds="http://schemas.android.com/apk/res/com.example.drawerlayoutdemo"
yds:rightPadding="100dp">
</LinearLayout>


2.然后是scrollTo的使用。这里我也是有点糊涂,就不写了,网上可以查找相关资料。

3.水平侧滑,所以SlidingMenu要继承自HorizontalScrollView。这里有个问题。SlidingMenu有三个构造函数,SlidingMenu(Context context)、SlidingMenu(Context context, AttributeSet attrs)、SlidingMenu(Context context, AttributeSet attrs,int defStyle)。在这里,我们要明确this和super的用法,super是调用父类的构造函数,this是调用本类中具有相同形参的构造函数。

如果如下面一样来写构造函数,则侧滑菜单是不能侧滑的,会出现bug。

public SlidingMenu(Context context, AttributeSet attrs) {
super(context, attrs,0);
// TODO Auto-generated constructor stub
}


这里的super应该改成this,我就是用了几个小时才发现这个错误的。

4.这里要用到nineoldandroids-2.4.0.jar

现在先上效果图:



完整布局文件及代码如下:

1.attr.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

<attr name="rightPadding" format="dimension" />

<declare-styleable name="SlidingMenu">
<attr name="rightPadding" />
</declare-styleable>
<declare-styleable name="CircleImageView">
<attr name="border_width" format="dimension" />
<attr name="border_color" format="color" />
</declare-styleable>
</resources>


2.layout_menu.xml

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"

xmlns:android="http://schemas.android.com/apk/res/android">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="11111"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="11111"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="11111"/>

</LinearLayout>
</RelativeLayout>


3.activity_main.xml,这里TextView的父控件要用LinearLayout,因为在SlidingMenu里的onMeasure方法中已经写了该相关代码,若是没有父控件,会报错。

<com.example.drawerlayoutdemo.SlidingMenu
android:id="@+id/slidingmenu"
xmlns:tools="http://schemas.android.com/tools"
xmlns:yds="http://schemas.android.com/apk/res/com.example.drawerlayoutdemo"
android:layout_width="wrap_content"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#ffffff"
android:scrollbars="none"
yds:rightPadding="100dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<include layout="@layout/layout_menu"/>
<LinearLayout
android:background="#d2691e"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="this is main page"/>
</LinearLayout>

</LinearLayout>
</com.example.drawerlayoutdemo.SlidingMenu>


4.SlidingMenu.java源码:

package com.example.drawerlayoutdemo;

import com.nineoldandroids.view.ViewHelper;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;

public class SlidingMenu extends HorizontalScrollView{
/**
* 屏幕宽度
*/
private int mScreenWidth;
/**
* 距离右边距
*
*/
private int mMenuRightPadding;
private boolean once;
private boolean isOpen;
private ViewGroup mMenu;
private ViewGroup mContent;

/**
* 菜单的宽度
*
*/
private int mMenuWidth;
private int mHalfMenuWidth;

//构造函数
public SlidingMenu(Context context){
this(context, null,0);
}
//构造函数
public SlidingMenu(Context context, AttributeSet attrs) {
this(context, attrs,0);
// TODO Auto-generated constructor stub
}
//构造函数
public SlidingMenu(Context context, AttributeSet attrs,int defStyle) {
super(context, attrs,defStyle);
// TODO Auto-generated constructor stub
mScreenWidth = getScreenWidth(context);
//自定义属性
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:
//默认50
mMenuRightPadding = a.getDimensionPixelSize(attr,
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
50f, getResources().getDisplayMetrics()));
break;

default:
break;
}
}
//回收
a.recycle();
}
/**
* 重写此方法,该方法是当父元素要放置该控件时调用
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
if (!once)
{
LinearLayout wrapper = (LinearLayout) getChildAt(0);
mMenu = (ViewGroup) wrapper.getChildAt(0);
mContent = (ViewGroup) wrapper.getChildAt(1);

mMenuWidth = mScreenWidth - mMenuRightPadding;
mHalfMenuWidth = mMenuWidth / 2;
mMenu.getLayoutParams().width = mMenuWidth;
mContent.getLayoutParams().width = mScreenWidth;

}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
super.onLayout(changed, l, t, r, b);
if(changed){
//将菜单隐藏
this.scrollTo(mMenuWidth, 0);
once = true;
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub

int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_UP:
//up时进行判断,当滑动距离大于菜单宽度一半时则完全显示
int scrollX = getScrollX();
if(scrollX > mHalfMenuWidth){
this.smoothScrollTo(mMenuWidth, 0);
isOpen = false;
}else{
this.smoothScrollTo(0, 0);
isOpen = true;
}

return true;

}
return super.onTouchEvent(ev);
}
/**
* 打开菜单
*/
public void openMenu(){
if(isOpen)
return;
this.smoothScrollTo(0, 0);
isOpen = true;
}
public void closeMenu(){
if(isOpen){
this.smoothScrollTo(mMenuWidth, 0);
isOpen = true;
}
}

public void toggle(){
if(isOpen){
closeMenu();
}else{
openMenu();
}
}

@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt)
{
super.onScrollChanged(l, t, oldl, oldt);
float scale = l * 1.0f / mMenuWidth;
float leftScale = 1 - 0.3f * scale;
float rightScale = 0.8f + scale * 0.2f;

ViewHelper.setScaleX(mMenu, leftScale);
ViewHelper.setScaleY(mMenu, leftScale);
ViewHelper.setAlpha(mMenu, 0.6f + 0.4f * (1 - scale));
ViewHelper.setTranslationX(mMenu, mMenuWidth * scale * 0.7f);

ViewHelper.setPivotX(mContent, 0);
ViewHelper.setPivotY(mContent, mContent.getHeight() / 2);
ViewHelper.setScaleX(mContent, rightScale);
ViewHelper.setScaleY(mContent, rightScale);

}

/**
* 获取屏幕宽度
* @param context
* @return 宽度像素
*/
private static int getScreenWidth(Context context){
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
//DisplayMetrics 类提供了一种关于显示的通用信息,如显示大小,分辨率和字体
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.widthPixels;
}
/**
* 获取屏幕高度
* @param context
* @return  高度像素
*/
private static int getScreenHeight(Context context){
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.heightPixels;
}
}


5.MainActivity.java源码:

package com.example.drawerlayoutdemo;

import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity {
private SlidingMenu mMenu;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMenu = (SlidingMenu) findViewById(R.id.slidingmenu);

}

}


源码下载:

http://download.csdn.net/detail/u013293125/9600241
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android
相关文章推荐