Android控件View打造完美的自定義側(cè)滑菜單
一、概述
在App中,經(jīng)常會(huì)出現(xiàn)側(cè)滑菜單,側(cè)滑滑出View等效果,雖然說Android有很多第三方開源庫(kù),但是實(shí)際上咱們可以自己也寫一個(gè)自定義的側(cè)滑View控件,其實(shí)不難,主要涉及到以下幾個(gè)要點(diǎn):
1.對(duì)Android中Window類中的DecorView有所了解
2.對(duì)Scroller類實(shí)現(xiàn)平滑移動(dòng)效果
3.自定義ViewGroup的實(shí)現(xiàn)
首先來看看效果圖吧:

下面現(xiàn)在就來說說這里咱們實(shí)現(xiàn)側(cè)滑View的基本思路吧,這里我采用的是自定義一個(gè)繼承于RelativeLayout的控件叫做XCSlideView類吧。
首先從布局文件中inflater出來一個(gè)menuView,然后通過addView的方法,將該側(cè)滑View添加到自定義的控件View中怎么讓XCSlideView 這個(gè)側(cè)滑View 隱藏到屏幕之外呢?很簡(jiǎn)單通過ScrollTo方法,移動(dòng)一個(gè)屏幕寬度的距離即可,這里以左側(cè)滑出為例吧,只需要這樣 XCSlideView.this.scrollTo(mScreenWidth, 0);mScreenWidth是屏幕寬度。下面還要處理的就是底下的半透明黑色的蒙層效果,這個(gè)其實(shí)就是一個(gè)View,然后設(shè)置半透明效果。這個(gè)當(dāng)然簡(jiǎn)單了,關(guān)鍵是咱們讓他顯示在咱們的自定義側(cè)滑View的下面呢,這里咱們先給出DecorView的簡(jiǎn)單分析,方便下面介紹添加半透明View蒙層下:

下面是對(duì)上面這張圖的解釋:
1、DecorView為整個(gè)Window界面的最頂層View。
2、DecorView只有一個(gè)子元素為L(zhǎng)inearLayout。代表整個(gè)Window界面,包含通知欄,標(biāo)題欄,內(nèi)容顯示欄三塊區(qū)域。
3、LinearLayout里有兩個(gè)FrameLayout子元素。
(20)為標(biāo)題欄顯示界面。只有一個(gè)TextView顯示應(yīng)用的名稱。也可以自定義標(biāo)題欄,載入后的自定義標(biāo)題欄View將加入FrameLayout中。
(21)為內(nèi)容欄顯示界面。就是setContentView()方法載入的布局界面,加入其中。
有了上面的DecorVIew知識(shí)背景,現(xiàn)在就來說說 怎么添加蒙層View和將自定義側(cè)滑View添加到Activity的DecorView中,首先把蒙層View添加到
(31)customView中去,然后將自定義側(cè)滑View添加到 (21)FrameLayout中去,至于為什么要這樣,是因?yàn)榭紤]到自定義側(cè)滑View不一定是寬度為屏幕寬度,所以才這么做,而且也方面處理有無標(biāo)題欄,有無采用沉浸式狀態(tài)欄設(shè)計(jì)等情況。
二、自定義側(cè)滑View的實(shí)現(xiàn)
根據(jù)上面的概述,大家應(yīng)該知道大概的思路了,下面我就給出自定義側(cè)滑View類的核心代碼:
1、自定義側(cè)滑View用到的變量:
//側(cè)滑方向-從哪側(cè)滑出
public static enum Positon {
LEFT, RIGHT
}
private Context mContext;
private Activity mActivity;
private Scroller mScroller = null;
//側(cè)滑菜單布局View
private View mMenuView;
//底部蒙層View
private View mMaskView;
private int mMenuWidth = 0;
//屏幕寬度
private int mScreenWidth = 0;
//是否在滑動(dòng)中
private boolean mIsMoving = false;
//顯示登錄界面與否
private boolean mShow = false;
//滑動(dòng)動(dòng)畫時(shí)間
private int mDuration = 600;
//缺省側(cè)滑方向?yàn)樽?
private Positon mPositon = Positon.LEFT;
2、初始化創(chuàng)建自定義側(cè)滑View:
**
* 創(chuàng)建側(cè)滑菜單View
*/
public static XCSlideView create(Activity activity) {
XCSlideView view = new XCSlideView(activity);
return view;
}
/**
* 創(chuàng)建側(cè)滑菜單View
*/
public static XCSlideView create(Activity activity, Positon positon) {
XCSlideView view = new XCSlideView(activity);
view.mPositon = positon;
return view;
}
3、創(chuàng)建半透明蒙層View,并添加到contentView中去
/**
* 創(chuàng)建 蒙層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、設(shè)置側(cè)滑菜單View,并添加到DectorView->LinearLayout->內(nèi)容顯示區(qū)域View(FrameLayout)中
/**
* 設(shè)置側(cè)滑菜單View,并添加到DectorView->LinearLayout->內(nèi)容顯示區(qū)域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){
//說明狀態(tài)欄使用沉浸式
layoutParams.topMargin = DensityUtil.getStatusBarHeight(mContext);
}
this.setLayoutParams(layoutParams);
}
5、處理自定義側(cè)滑View的側(cè)滑滑動(dòng)和隱藏效果:
/**
* 顯示側(cè)滑菜單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;
}
/**
* 蒙層顯示開關(guān)
*/
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);
}
}
/**
* 關(guān)閉側(cè)滑菜單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();
}
/**
* 拖動(dòng)移動(dòng)
*/
public void startScroll(int startX, int dx,int duration){
mIsMoving = true;
mScroller.startScroll(startX,0,dx,0,duration);
invalidate();
}
三、如何使用該自定義側(cè)滑View控件
使用起來,比較簡(jiǎn)單,通過create方法創(chuàng)建一個(gè)側(cè)滑VIew,然后通過setMenuView方法設(shè)置一個(gè)側(cè)滑View進(jìn)去,有需要設(shè)置寬度的話, 通過setMenuWidth方法來設(shè)置即可,最后用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();
}
});
四、源碼下載
下載:側(cè)滑菜單
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android編程之下拉菜單Spinner控件用法示例
- Android自定義控件實(shí)現(xiàn)底部菜單(下)
- Android自定義控件實(shí)現(xiàn)底部菜單(上)
- Android 中 SwipeLayout一個(gè)展示條目底層菜單的側(cè)滑控件源碼解析
- Android自定義控件案例匯總1(菜單、popupwindow、viewpager)
- Android自定義控件簡(jiǎn)單實(shí)現(xiàn)側(cè)滑菜單效果
- Android自定義控件之仿優(yōu)酷菜單
- Android使用自定義控件HorizontalScrollView打造史上最簡(jiǎn)單的側(cè)滑菜單
- Android控件之菜單的創(chuàng)建方式
相關(guān)文章
android教程使用webview訪問https的url處理sslerror示例
這篇文章主要介紹了android教程使用webview訪問https的url處理sslerror示例,大家參考使用吧2014-01-01
通過FancyView提供 Android 酷炫的開屏動(dòng)畫實(shí)例代碼
這篇文章主要介紹了通過FancyView提供 Android 酷炫的開屏動(dòng)畫的實(shí)現(xiàn)代碼,需要的朋友可以參考下2017-12-12
Android自定義控件實(shí)現(xiàn)方向盤效果
這篇文章主要為大家詳細(xì)介紹了Android自定義控件實(shí)現(xiàn)方向盤效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04
Android自定義view實(shí)現(xiàn)仿抖音點(diǎn)贊效果
這篇文章主要介紹了Android自定義view實(shí)現(xiàn)仿抖音點(diǎn)贊效果,代碼簡(jiǎn)單易懂非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-05-05
Android studio 廣播的簡(jiǎn)單使用代碼詳解
這篇文章主要介紹了Android studio 廣播的簡(jiǎn)單使用,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04
Android從源碼的角度徹底理解事件分發(fā)機(jī)制的解析(上)
這篇文章主要介紹了Android從源碼的角度徹底理解事件分發(fā)機(jī)制的解析,具有很好的參考價(jià)值,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-05-05

