android 侧滑菜单 实现

时间:2021-03-22 15:32:30

android自定义控件侧滑用HorizontalScrollView来实现

1、在开始之前我们先了解onLayout()、onMeasure()两个方法

onLayout():官方解释:Called from layout when this view should assign a size and position to each of its children. Derived classes with children should override this method and call layout on each of their children.

(从布局时调用这个观点应该分配一个大小和位置,以它的每一个孩子。派生类的儿童应该重写此方法,并调用布局上的每个孩子。)

onMeasure():Measure the view and its content to determine the measured width and the measured height. This method is invoked by measure(int, int) and should be overriden by subclasses to provide accurate and efficient measurement of their contents. 

在了解这俩个方法后我们要重写这两个方法

2、写获取屏幕相关的辅助类

public class ScreenUtils
{
private ScreenUtils()
{
/* cannot be instantiated */
throw new UnsupportedOperationException("cannot be instantiated");
}

/**
* 获得屏幕高度
*
* @param context
* @return
*/
public static int getScreenWidth(Context context)
{
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.widthPixels;
}

/**
* 获得屏幕宽度
*
* @param context
* @return
*/
public static int getScreenHeight(Context context)
{
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.heightPixels;
}

/**
* 获得状态栏的高度
*
* @param context
* @return
*/
public static int getStatusHeight(Context context)
{

int statusHeight = -1;
try
{
Class<?> clazz = Class.forName("com.android.internal.R$dimen");
Object object = clazz.newInstance();
int height = Integer.parseInt(clazz.getField("status_bar_height")
.get(object).toString());
statusHeight = context.getResources().getDimensionPixelSize(height);
} catch (Exception e)
{
e.printStackTrace();
}
return statusHeight;
}

/**
* 获取当前屏幕截图,包含状态栏
*
* @param activity
* @return
*/
public static Bitmap snapShotWithStatusBar(Activity activity)
{
View view = activity.getWindow().getDecorView();
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap bmp = view.getDrawingCache();
int width = getScreenWidth(activity);
int height = getScreenHeight(activity);
Bitmap bp = null;
bp = Bitmap.createBitmap(bmp, 0, 0, width, height);
view.destroyDrawingCache();
return bp;

}

/**
* 获取当前屏幕截图,不包含状态栏
*
* @param activity
* @return
*/
public static Bitmap snapShotWithoutStatusBar(Activity activity)
{
View view = activity.getWindow().getDecorView();
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap bmp = view.getDrawingCache();
Rect frame = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;

int width = getScreenWidth(activity);
int height = getScreenHeight(activity);
Bitmap bp = null;
bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height
- statusBarHeight);
view.destroyDrawingCache();
return bp;

}

}
3、自定义SlidingMenu

核心代码;

public class slidingmenu extends HorizontalScrollView {
// 屏幕的宽度
private int mScreenWidth;
// dp
private int mMenuRightPadding = 50;
// 菜单的宽度
private int mMenuWidth;
private int mHalfMenuWodth;

private boolean once;

private boolean isOpen;

public slidingmenu(Context context, AttributeSet attrs) {
this(context, attrs, 0);
// mScreenWidth=ScreenUtils.get
}

public slidingmenu(Context context, AttributeSet attrs, int defSytyle) {
super(context, attrs, defSytyle);
mScreenWidth = ScreenUtils.getScreenWidth(context);
TypedArray array = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.SlidingMenu, defSytyle, 0);
int n = array.getIndexCount();
for (int i = 0; i < n; i++) {
int attr = array.getIndex(i);
switch (attr) {
case R.styleable.SlidingMenu_rightPadding:
// 默认50
mMenuRightPadding = array.getDimensionPixelSize(attr,
(int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 50f,
getResources().getDisplayMetrics()));//默认为10dp
break;

default:
break;
}

}
array.recycle();
}
public slidingmenu(Context context){
this(context, null,0);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
//显示的设置一个高度
if (!once) {
LinearLayout wrapper=(LinearLayout)getChildAt(0);
ViewGroup menu=(ViewGroup)wrapper.getChildAt(0);
ViewGroup content=(ViewGroup)wrapper.getChildAt(1);

mMenuWidth=mScreenWidth-mMenuRightPadding;
mHalfMenuWodth=mMenuWidth/2;
menu.getLayoutParams().width=mMenuWidth;
content.getLayoutParams().width=mScreenWidth;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
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);
once=true;
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action=ev.getAction();
switch (action) {
//UP 时 ,进行判断,如果显示区域大于菜单宽度一半则完全显示,否则隐藏
case MotionEvent.ACTION_UP:
int scrollX=getScrollX();
if (scrollX > mHalfMenuWodth) {
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=false;
}
}
//切换菜单状态
public void toggle(){
if (isOpen) {
closeMenu();
}else {
openMenu();
}
}

}
4、扩展

 1、添加自定义属性

a、在values文件夹下新建一个attr.xml

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

<declare-styleable name="SlidingMenu">
<attr name="rightPadding" />
</declare-styleable>
</resources>
b、布局文件

activity_main.xml

<com.example.slidingmenu.slidingmenu xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/id_menu"
xmlns:tools="http://schemas.android.com/tools"
xmlns:zhy="http://schemas.android.com/apk/res/com.example.slidingmenu"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:background="@drawable/img_frame_background"
android:scrollbars="none"
zhy:rightPadding="100dp" >

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:orientation="horizontal" >

<include layout="@layout/layout_menu" />

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/qq" >

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="toggleMenu"
android:text="切换菜单" />
</LinearLayout>
</LinearLayout>

</com.example.slidingmenu.slidingmenu>

layout_menu.xml

<?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"
android:background="#0000" >

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:orientation="vertical" >

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

<ImageView
android:id="@+id/one"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@drawable/img_1" />

<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/one"
android:text="第1个Item"
android:textColor="#f0f0f0"
android:textSize="20sp" />
</RelativeLayout>

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

<ImageView
android:id="@+id/two"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@drawable/img_2" />

<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/two"
android:text="第2个Item"
android:textColor="#f0f0f0"
android:textSize="20sp" />
</RelativeLayout>

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

<ImageView
android:id="@+id/three"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@drawable/img_3" />

<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/three"
android:text="第3个Item"
android:textColor="#f0f0f0"
android:textSize="20sp" />
</RelativeLayout>

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

<ImageView
android:id="@+id/four"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@drawable/img_4" />

<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/four"
android:text="第一个Item"
android:textColor="#f0f0f0"
android:textSize="20sp" />
</RelativeLayout>

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

<ImageView
android:id="@+id/five"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@drawable/img_5" />

<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/five"
android:text="第5个Item"
android:textColor="#f0f0f0"
android:textSize="20sp" />
</RelativeLayout>
</LinearLayout>

</RelativeLayout>

5、最后一步在主Activity中调用

public class MainActivity extends ActionBarActivity {

private slidingmenu slidingmenu;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
slidingmenu=(slidingmenu)findViewById(R.id.id_menu);


}
public void toggleMenu(View view)
{
slidingmenu.toggle();
}


}

最后看一下效果图

android 侧滑菜单 实现

源码下载点击打开链接android 侧滑菜单 实现