Android 打造完美的側滑選單/側滑View控制元件
一.概述
在App中,經常會出現側滑選單,側滑滑出View等效果,雖然說Android有很多第三方開源庫,但是實際上
咱們可以自己也寫一個自定義的側滑View控制元件,其實不難,主要涉及到以下幾個要點:
1.對Android中Window類中的DecorView有所瞭解
2.對Scroller類實現平滑移動效果
3.自定義ViewGroup的實現
下面現在就來說說這裡咱們實現側滑View的基本思路吧,這裡我採用的是自定義一個繼承於RelativeLayout的控制元件叫做XCSlideView類吧。
首先從佈局檔案中inflater出來一個menuView,然後通過addView的方法,將該側滑View新增到自定義的控制元件View中
怎麼讓XCSlideView 這個側滑View 隱藏到螢幕之外呢?很簡單通過ScrollTo方法,移動一個螢幕寬度的距離即可,這裡以
左側滑出為例吧,只需要這樣 XCSlideView.this.scrollTo(mScreenWidth, 0);mScreenWidth是螢幕寬度。下面還要處理的就是底下的
半透明黑色的蒙層效果,這個其實就是一個View,然後設定半透明效果。這個當然簡單了,關鍵是咱們讓他顯示在咱們的自定義側滑View的下面呢,
這裡咱們先給出DecorView的簡單分析,方便下面介紹新增半透明View蒙層下:
二.演示效果圖
三.程式碼實現過程解析
根據上面的概述,大家應該知道大概的思路了,下面我就給出自定義側滑View類的核心程式碼:
1、自定義側滑View用到的變數:
//側滑方向-從哪側滑出 public static enum Positon { LEFT, RIGHT } private Context mContext; private Activity mActivity; private Scroller mScroller = null; //側滑選單佈局View private View mMenuView; //底部蒙層View private View mMaskView; private int mMenuWidth = 0; //螢幕寬度 private int mScreenWidth = 0; //是否在滑動中 private boolean mIsMoving = false; //顯示登入介面與否 private boolean mShow = false; //滑動動畫時間 private int mDuration = 600; //預設側滑方向為左 private Positon mPositon = Positon.LEFT;
2、初始化建立自定義側滑View:
**
* 建立側滑選單View
*/
public static XCSlideView create(Activity activity) {
XCSlideView view = new XCSlideView(activity);
return view;
}
/**
* 建立側滑選單View
*/
public static XCSlideView create(Activity activity, Positon positon) {
XCSlideView view = new XCSlideView(activity);
view.mPositon = positon;
return view;
}
3、建立半透明蒙層View,並新增到contentView中去
/**
* 建立 蒙層View並新增到contentView中
*/
private void attachToContentView(Activity activity, Positon positon) {
mPositon = positon;
ViewGroup contentFrameLayout = (ViewGroup) activity.findViewById(android.R.id.content);
ViewGroup contentView = ((ViewGroup) contentFrameLayout.getChildAt(0));
mMaskView = new View(activity);
mMaskView.setBackgroundColor(mContext.getResources().getColor(R.color.mask_color));
contentView.addView(mMaskView, contentView.getLayoutParams());
mMaskView.setVisibility(View.GONE);
mMaskView.setClickable(true);
mMaskView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (isShow()) {
dismiss();
}
}
});
}
4、設定側滑選單View,並新增到DectorView->LinearLayout->內容顯示區域View(FrameLayout)中
/**
* 設定側滑選單View,並新增到DectorView->LinearLayout->內容顯示區域View中
*/
public void setMenuView(Activity activity, View view) {
mActivity = activity;
mMenuView = view;
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
addView(mMenuView, params);
mMenuView.post(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
mMenuWidth = mMenuView.getWidth();
switch (mPositon) {
case LEFT:
XCSlideView.this.scrollTo(mScreenWidth, 0);
break;
case RIGHT:
XCSlideView.this.scrollTo(-mScreenWidth, 0);
break;
}
}
});
ViewGroup contentFrameLayout = (ViewGroup) activity.findViewById(android.R.id.content);
ViewGroup contentView = contentFrameLayout;
contentView.addView(this);
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) this.getLayoutParams();
switch (mPositon) {
case LEFT:
layoutParams.gravity = Gravity.LEFT;
layoutParams.leftMargin = 0;
break;
case RIGHT:
layoutParams.gravity = Gravity.RIGHT;
layoutParams.rightMargin = 0;
break;
}
TextView titleFrameLayout = (TextView) activity.findViewById(android.R.id.title);
if( titleFrameLayout != null){
layoutParams.topMargin = DensityUtil.getStatusBarHeight(mContext);
}
int flags = mActivity.getWindow().getAttributes().flags;
int flag = (flags & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
if(flag == WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS){
//說明狀態列使用沉浸式
layoutParams.topMargin = DensityUtil.getStatusBarHeight(mContext);
}
this.setLayoutParams(layoutParams);
}
5、處理自定義側滑View的側滑滑動和隱藏效果:
/**
* 顯示側滑選單View
*/
public void show(){
if(isShow() && !mIsMoving)
return;
switch (mPositon) {
case LEFT:
startScroll(mMenuWidth, -mMenuWidth, mDuration);
break;
case RIGHT:
startScroll(-mMenuWidth, mMenuWidth, mDuration);
break;
}
switchMaskView(true);
mShow = true;
}
/**
* 蒙層顯示開關
*/
private void switchMaskView(boolean bShow){
if(bShow){
mMaskView.setVisibility(View.VISIBLE);
Animation animation = new AlphaAnimation(0.0f, 1.0f);
animation.setDuration(mDuration);
mMaskView.startAnimation(animation);
}else{
mMaskView.setVisibility(View.GONE);
}
}
/**
* 關閉側滑選單View
*/
public void dismiss() {
// TODO Auto-generated method stub
if(!isShow() && !mIsMoving)
return;
switch (mPositon) {
case LEFT:
startScroll(XCSlideView.this.getScrollX(), mMenuWidth, mDuration);
break;
case RIGHT:
startScroll(XCSlideView.this.getScrollX(), -mMenuWidth, mDuration);
break;
}
switchMaskView(false);
mShow = false;
}
public boolean isShow(){
return mShow;
}
@Override
public void computeScroll() {
// TODO Auto-generated method stub
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
// 更新介面
postInvalidate();
mIsMoving = true;
} else {
mIsMoving = false;
}
super.computeScroll();
}
/**
* 拖動移動
*/
public void startScroll(int startX, int dx,int duration){
mIsMoving = true;
mScroller.startScroll(startX,0,dx,0,duration);
invalidate();
}
四.如何使用該自定義側滑View控制元件
使用起來,比較簡單,通過create方法建立一個側滑VIew,然後通過setMenuView方法設定一個側滑View進去,有需要設定
寬度的話, 通過setMenuWidth方法來設定即可,最後用show()方法滑出來就可以啦,使用起來是不是很方便?
private XCSlideView mSlideViewLeft;
//螢幕寬度
private int mScreenWidth = 0;
View menuViewLeft = LayoutInflater.from(mContext).inflate(R.layout.layout_slideview,null);
mSlideViewLeft = XCSlideView.create(this, XCSlideView.Positon.LEFT);
mSlideViewLeft.setMenuView(MainActivity.this, menuViewLeft);
mSlideViewLeft.setMenuWidth(mScreenWidth * 7 / 9);
Button left = (Button)findViewById(R.id.btn_left);
left.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (!mSlideViewLeft.isShow())
mSlideViewLeft.show();
}
});
五.專案程式碼結構圖