Android自定義控件簡(jiǎn)單實(shí)現(xiàn)側(cè)滑菜單效果
側(cè)滑菜單在很多應(yīng)用中都會(huì)見(jiàn)到,最近QQ5.0側(cè)滑還玩了點(diǎn)花樣~~對(duì)于側(cè)滑菜單,一般大家都會(huì)自定義ViewGroup,然后隱藏菜單欄,當(dāng)手指滑動(dòng)時(shí),通過(guò)Scroller或者不斷的改變leftMargin等實(shí)現(xiàn);多少都有點(diǎn)復(fù)雜,完成以后還需要對(duì)滑動(dòng)沖突等進(jìn)行處理~~今天給大家?guī)?lái)一個(gè)簡(jiǎn)單的實(shí)現(xiàn),史上最簡(jiǎn)單有點(diǎn)夸張,但是的確是我目前遇到過(guò)的最簡(jiǎn)單的一種實(shí)現(xiàn)~~~
1、原理分析
既然是側(cè)滑,無(wú)非就是在巴掌大的屏幕,塞入大概兩巴掌大的布局,需要滑動(dòng)可以出現(xiàn)另一個(gè),既然這樣,大家為啥不考慮使用Android提供的HorizontalScrollView呢~
如果使用HorizontalScrollView,還需要在ACTION_DOWN , ACTION_MOVE里面去監(jiān)聽(tīng),判斷,不斷改變控件位置了么? NO?。?!HorizontalScrollView本身就帶了滑動(dòng)的功能~~
還需要自己的手動(dòng)處理各種沖突么?NO?。?!當(dāng)然了,還是需要了解下事件分發(fā)機(jī)制的~~~
2、效果圖

嗯,主界面搞了QQ一張圖片,左邊盜用了一兄弟的布局文件~~罪過(guò)~~ 誰(shuí)有好看的布局、圖片、圖標(biāo)神馬的,可以給我發(fā)點(diǎn),感激~
3、布局文件
<com.example.zhy_slidingmenu.SlidingMenu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="fill_parent" android:scrollbars="none" > <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" > </LinearLayout> </LinearLayout> </com.example.zhy_slidingmenu.SlidingMenu>
首先是我們的自定義View,里面一個(gè)方向水平的LinearLayout,然后就是一個(gè)是菜單的布局,一個(gè)是主布局了~
4、自定義SlidingMenu
接下來(lái)就是我們最核心的代碼了~
package com.example.zhy_slidingmenu;
import android.content.Context;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import com.zhy.utils.ScreenUtils;
public class SlidingMenu extends HorizontalScrollView
{
/**
* 屏幕寬度
*/
private int mScreenWidth;
/**
* dp
*/
private int mMenuRightPadding = 50;
/**
* 菜單的寬度
*/
private int mMenuWidth;
private int mHalfMenuWidth;
private boolean once;
public SlidingMenu(Context context, AttributeSet attrs)
{
super(context, attrs);
mScreenWidth = ScreenUtils.getScreenWidth(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
/**
* 顯示的設(shè)置一個(gè)寬度
*/
if (!once)
{
LinearLayout wrapper = (LinearLayout) getChildAt(0);
ViewGroup menu = (ViewGroup) wrapper.getChildAt(0);
ViewGroup content = (ViewGroup) wrapper.getChildAt(1);
// dp to px
mMenuRightPadding = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, mMenuRightPadding, content
.getResources().getDisplayMetrics());
mMenuWidth = mScreenWidth - mMenuRightPadding;
mHalfMenuWidth = 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時(shí),進(jìn)行判斷,如果顯示區(qū)域大于菜單寬度一半則完全顯示,否則隱藏
case MotionEvent.ACTION_UP:
int scrollX = getScrollX();
if (scrollX > mHalfMenuWidth)
this.smoothScrollTo(mMenuWidth, 0);
else
this.smoothScrollTo(0, 0);
return true;
}
return super.onTouchEvent(ev);
}
}
哈哈,完工~上面的演示圖,就用到這么點(diǎn)代碼~~
代碼怎么樣,短不短~除了設(shè)置寬度這些雜七雜八的代碼~正在處理滑動(dòng)的代碼不過(guò)10行~~我說(shuō)史上最簡(jiǎn)單不為過(guò)吧~
嗯,由于代碼過(guò)于短,就不解釋了,大家自己看下注釋~
5、擴(kuò)展
嗯,就下來(lái),我們完善下程序,我準(zhǔn)備首先把菜單布局里面改成ListView來(lái)證明我們是沒(méi)有沖突的;然后添加一個(gè)屬性讓用戶(hù)配置菜單距離右邊的邊距的值;再對(duì)外公布一個(gè)方法,點(diǎn)擊自動(dòng)打開(kāi)菜單,供用戶(hù)點(diǎn)擊某個(gè)按鈕,菜單慢慢滑出來(lái)~
1)、添加自定義屬性
a、首先在values文件夾下新建一個(gè)attr.xml,寫(xiě)入以下內(nèi)容:
<?xml version="1.0" encoding="utf-8"?> <resources> <attr name="rightPadding" format="dimension" /> <declare-styleable name="SlidingMenu"> <attr name="rightPadding" /> </declare-styleable> </resources>
b、在布局中聲明命名空間和使用屬性
定義完了,肯定要使用么。
<com.example.zhy_slidingmenu.SlidingMenu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:zhy="http://schemas.android.com/apk/res/com.example.zhy_slidingmenu" android:layout_width="wrap_content" android:layout_height="fill_parent" android:scrollbars="none" zhy:rightPadding="100dp" >
可以看到我們的命名空間:xmlns:zhy="http://schemas.android.com/apk/res/com.example.zhy_slidingmenu" 是http://schemas.android.com/apk/res/加上我們的包名;
我們的屬性:zhy:rightPadding="100dp"這里我設(shè)置了100dp;
注:很多人問(wèn)我,沒(méi)有提示咋辦,這樣,你clean下項(xiàng)目,如果你運(yùn)氣好,就有提示了,嗯,運(yùn)氣好~
c、在我們自定義類(lèi)中獲得屬性
public SlidingMenu(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
mScreenWidth = ScreenUtils.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:
// 默認(rèn)50
mMenuRightPadding = a.getDimensionPixelSize(attr,
(int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 50f,
getResources().getDisplayMetrics()));// 默認(rèn)為10DP
break;
}
}
a.recycle();
}
在三個(gè)參數(shù)的構(gòu)造方法中,通過(guò)TypeArray獲取就行了~
好了,這樣就行了~如果你又很多自定義屬性,按照上面的步驟來(lái)就行了~~
2)、對(duì)外公布一個(gè)打開(kāi)菜單的方法
首先定義一個(gè)boolean isOpen變量,用來(lái)標(biāo)識(shí)我們當(dāng)前菜單的狀態(tài)~~然后記得在ACTION_UP的時(shí)候改變下?tīng)顟B(tài):
case MotionEvent.ACTION_UP:
int scrollX = getScrollX();
if (scrollX > mHalfMenuWidth)
{
this.smoothScrollTo(mMenuWidth, 0);
isOpen = false;
} else
{
this.smoothScrollTo(0, 0);
isOpen = true;
}
return true;
}
下面開(kāi)始添加方法:
/**
* 打開(kāi)菜單
*/
public void openMenu()
{
if (isOpen)
return;
this.smoothScrollTo(0, 0);
isOpen = true;
}
/**
* 關(guān)閉菜單
*/
public void closeMenu()
{
if (isOpen)
{
this.smoothScrollTo(mMenuWidth, 0);
isOpen = false;
}
}
/**
* 切換菜單狀態(tài)
*/
public void toggle()
{
if (isOpen)
{
closeMenu();
} else
{
openMenu();
}
}
順手多添加了兩個(gè)。。。
下面,我們挑一個(gè)進(jìn)行測(cè)試:
主布局多添加一個(gè)按鈕,用于觸發(fā)toggleMenu()方法
主Activity
public class MainActivity extends Activity
{
private SlidingMenu mMenu ;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
mMenu = (SlidingMenu) findViewById(R.id.id_menu);
}
public void toggleMenu(View view)
{
mMenu.toggle();
}
}
好了,看下現(xiàn)在的效果圖:

我們把padding改成了100dp~
然后點(diǎn)擊我們的按鈕,看哈效果~~
3)、添加ListView測(cè)試

好了~~ListView也測(cè)試完了~~大家可以根據(jù)自己的需求各種修改~~
對(duì)了,今天測(cè)試用QQ的目的是為了,下次我要拿上面的代碼,改造和QQ5.0一模一樣的效果,大家有興趣可以提前試一試,QQ的菜單好像是隱藏在主界面下面一樣,給人感覺(jué)不是劃出來(lái)的,我們這個(gè)例子也能做出那樣的效果,拭目以待吧;剩下就是各種縮放,透明度的動(dòng)畫(huà)了~~~
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
本文出自【張鴻洋的博客】
- Android開(kāi)發(fā)技巧之我的菜單我做主(自定義菜單)
- android自定義popupwindow仿微信右上角彈出菜單效果
- Android實(shí)現(xiàn)自定義滑動(dòng)式抽屜菜單效果
- android 自定義Android菜單背景的代碼
- Android自定義ViewGroup實(shí)現(xiàn)帶箭頭的圓角矩形菜單
- Android自定義view實(shí)現(xiàn)圓形與半圓形菜單
- Android實(shí)現(xiàn)自定義的衛(wèi)星式菜單(弧形菜單)詳解
- Android編程自定義菜單實(shí)現(xiàn)方法詳解
- Android 自定義彈出菜單和對(duì)話(huà)框功能實(shí)例代碼
- Android自定義View展開(kāi)菜單功能的實(shí)現(xiàn)
- Android使用xml文件資源定義菜單實(shí)現(xiàn)方法示例
相關(guān)文章
Android通過(guò)aapt命令獲取apk詳細(xì)信息(包括:文件包名,版本號(hào),SDK等信息)
本文給大家分享android通過(guò)aapt命令獲取apk詳細(xì)信息(包括:文件包名,版本號(hào),SDK等信息),非常不錯(cuò),簡(jiǎn)單實(shí)用,對(duì)android sdk aapt知識(shí)感興趣的朋友一起通過(guò)本文學(xué)習(xí)吧2016-11-11
Android廣播實(shí)現(xiàn)App開(kāi)機(jī)自啟動(dòng)
這篇文章主要為大家詳細(xì)介紹了Android廣播實(shí)現(xiàn)App開(kāi)機(jī)自啟動(dòng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
Activity配置、啟動(dòng)和關(guān)閉activity實(shí)例詳解
這篇文章主要介紹了Activity配置、啟動(dòng)和關(guān)閉activity實(shí)例詳解,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09
Android數(shù)據(jù)庫(kù)greenDAO配置與使用介紹
這篇文章主要介紹了Android集成GreenDao數(shù)據(jù)庫(kù),使用數(shù)據(jù)庫(kù)存儲(chǔ)時(shí)候,一般都會(huì)使用一些第三方ORM框架,比如GreenDao,本文分幾步給大家介紹Android集成GreenDao數(shù)據(jù)庫(kù)的方法,需要的朋友可以參考下2023-03-03
Android仿今日頭條APP實(shí)現(xiàn)下拉導(dǎo)航選擇菜單效果
這篇文章主要為大家詳細(xì)介紹了Android仿今日頭條APP實(shí)現(xiàn)下拉導(dǎo)航選擇菜單效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-06-06
Android使用Handler實(shí)現(xiàn)打地鼠游戲
這篇文章主要為大家詳細(xì)介紹了Android使用Handler實(shí)現(xiàn)打地鼠游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06
Android入門(mén)之Glide顯示網(wǎng)絡(luò)圖片高版本的使用詳解
這篇文章主要為大家詳細(xì)介紹了Android中Glide顯示網(wǎng)絡(luò)圖片高版本的使用方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2023-02-02
Android ProgressBar直線(xiàn)進(jìn)度條的實(shí)例代碼
本文通過(guò)實(shí)例代碼給大家介紹了android progressbar直線(xiàn)進(jìn)度條的實(shí)現(xiàn)方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-06-06
Flutter框架實(shí)現(xiàn)Android拖動(dòng)到垃圾桶刪除效果
這篇文章主要介紹了Flutter框架實(shí)現(xiàn)Android拖動(dòng)到垃圾桶刪除效果,Flutter框架中的Draggable部件,用于支持用戶(hù)通過(guò)手勢(shì)拖動(dòng),它是基于手勢(shì)的一種方式,可以使用戶(hù)可以在屏幕上拖動(dòng)指定的部件,下面我們來(lái)詳細(xì)了解一下2023-12-12
Android 逐幀動(dòng)畫(huà)創(chuàng)建實(shí)例詳解
這篇文章主要介紹了Android 逐幀動(dòng)畫(huà)創(chuàng)建實(shí)例詳解的相關(guān)資料,這里主要說(shuō)明Android 動(dòng)畫(huà)的創(chuàng)建及使用方法,希望通過(guò)此文能幫助到大家,需要的朋友可以參考下2017-08-08

