本篇只是个示例,理解本篇博客后,可实现左侧滑动菜单、左右两侧滑动菜单。再加上各种缩放,平移特效。DuangDuang的。本篇效果如下:
package com.example.chouti;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
public class SlidingRightView extends HorizontalScrollView {
/** * 主布局界面 */
private ViewGroup mMainLayout;
/** * 侧滑界面 */
private ViewGroup mRightLayout;
/** * 侧滑界面宽度 */
private int mRightLayoutWidth;
/** * 侧滑界面距离屏幕左边的距离 */
private int mRightLayoutMarginLeft = 200; //px
/** * 是否展示侧滑 */
private boolean isOpen;
private int mScreenWidth;
private int mScreenHeight;
private Context mContext;
public SlidingRightView(Context context) {
this(context, null);
}
public SlidingRightView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SlidingRightView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView(context);
}
private void initView(Context context) {
mContext = context;
getScreenWidthAndHeight();
}
private void getScreenWidthAndHeight() {
WindowManager wm = (WindowManager) mContext.getSystemService(mContext.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
mScreenWidth = outMetrics.widthPixels;
mScreenHeight = outMetrics.heightPixels;
Log.i("TAG", "mScreenWidth=" + mScreenWidth + "mScreenHeight=" + mScreenHeight);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
LinearLayout v = (LinearLayout) this.getChildAt(0);
mMainLayout = (ViewGroup) v.getChildAt(0);
mRightLayout = (ViewGroup) v.getChildAt(1);
mMainLayout.getLayoutParams().width = mScreenWidth;
mRightLayout.getLayoutParams().width = mRightLayoutWidth = mScreenWidth - mRightLayoutMarginLeft;
Log.i("TAG", " mRightLayout.getLayoutParams().width=" + mRightLayout.getLayoutParams().width);
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(0, 0);
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_UP:
// scrollX为水平滚动条滚动的宽度
int scrollX = getScrollX();
if (scrollX >= mRightLayoutWidth / 2) {
this.smoothScrollTo(mRightLayoutWidth, 0);
isOpen = true;
} else {
this.smoothScrollTo(0, 0);
isOpen = false;
}
// 拦截事件
return true;
}
return super.onTouchEvent(ev);
}
/** * 抽屉开关 */
public void toggleRightLayout() {
if (isOpen) {
closeRightLayout();
isOpen = false;
} else {
openRightLayout();
isOpen = true;
}
}
/** * 打开抽屉 */
public void openRightLayout() {
if (isOpen) {
return;
}
this.smoothScrollTo(mRightLayoutWidth, 0);
isOpen = true;
}
/** * 关闭抽屉 */
public void closeRightLayout() {
if (!isOpen) {
return;
}
this.smoothScrollTo(0, 0);
isOpen = false;
}
}
上文是前三步工程,完成上面三步之后我们已经有一个基础的滑动布局了。下面对上段代码进行解析。可以看到我们首先获取了屏幕的宽高。在onMeasure中我们为SlingRightView唯一childView的第一个childView和第二个childView宽赋值。在onLayout中默认不显示右侧布局。在onTouchEvent中判断滑动的宽度,如果大于右侧布局宽度的一半,则完全展示右侧布局。否则,不展示右侧布局。拦截当前事件。自定义View流程和拦截点击事件不太了解的同学可以看下我的另外两篇博客自定义View总结 Android 事件传递机制
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
float scale = l * 1.0f / mRightLayoutWidth;// 0.0~1.0
// 将mRightLayout平移l(第一个参数) 实现抽屉式侧滑菜单
// 这是个相对运动的过程 一定要注意理解
mMainLayout.setTranslationX(mRightLayoutWidth * scale);
}
两行代码实现抽屉式菜单。 第一个参数l为HorizontalScrollView偏移的长度(其实和getScrollX等价) 初始化时没有滑动,此时l=0。这里使用了属性动画。因为是右边布局滑动,主布局需要跟随手势滑动,滑动距离等于右侧布局的宽度。主布局看起来就像是一直“固定”在页面一样,其实是动态的滑动。mMainLayout.setTranslationX(mRightLayoutWidth * scale);
抽屉的精髓就是这行代码,一定要理解这个相对运动。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">
<com.example.chouti.SlidingRightView android:id="@+id/sliding" android:layout_width="wrap_content" android:layout_height="match_parent">
<LinearLayout android:layout_width="wrap_content" android:layout_height="match_parent" android:orientation="horizontal">
<LinearLayout android:id="@+id/mainLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ff0000" android:orientation="vertical">
<Button android:id="@+id/open" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="open" android:textAllCaps="false" />
<Button android:id="@+id/close" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="close" android:textAllCaps="false" />
<Button android:id="@+id/toggle" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="toggle" android:textAllCaps="false" />
</LinearLayout>
<LinearLayout android:id="@+id/rightLayout" android:layout_width="wrap_content" android:layout_height="match_parent" android:background="#00ff00" android:orientation="vertical">
<Button android:id="@+id/test" android:layout_width="match_parent" android:layout_height="wrap_content" android:textAllCaps="false" android:text="test" />
</LinearLayout>
</LinearLayout>
</com.example.chouti.SlidingRightView>
</LinearLayout>
package com.example.chouti;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.Toast;
public class MainActivity extends Activity {
private SlidingRightView slidingRightView;
@Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
slidingRightView = (SlidingRightView) findViewById(R.id.sliding);
findViewById(R.id.open).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
slidingRightView.openRightLayout();
}
});
findViewById(R.id.close).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
slidingRightView.closeRightLayout();
}
});
findViewById(R.id.toggle).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
slidingRightView.toggleRightLayout();
}
});
findViewById(R.id.test).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "click test", Toast.LENGTH_SHORT).show();
}
});
}
}
想要实现更酷炫的特效当然要用到动画。比如将抽屉进行缩放啦,透明度的变化了。具体看项目需求,下面是个简单的示例。
// 为mRightLayout设置缩放和透明度的变化
mRightLayout.setScaleX(mRightLayoutScale);
mRightLayout.setScaleY(mRightLayoutScale);
mRightLayout.setAlpha(mRightLayoutAlpha);
右滑抽屉式菜单到此已经完毕,感谢耐心读完。再次重申:这只是个Demo。现在假设需要左滑抽屉、左右滑抽屉、甚至更变态的各种滑,如果你有思路那么本篇博客的目的达到了。如果没有,建议重新阅读本篇博客。