Android實現(xiàn)3種側(cè)滑效果(仿qq側(cè)滑、抽屜側(cè)滑、普通側(cè)滑)
自己實現(xiàn)了一下側(cè)滑的三種方式(注釋都寫代碼里了)
本文Demo下載地址:Andriod側(cè)滑
本文實現(xiàn)所需框架:nineoldandroids下載地址:nineoldandroids
1.普通側(cè)滑:
主要是基于HorizontalScrollView做的:示例代碼如下
主要布局:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:gaoyu="http://schemas.android.com/apk/res/gaoyu.com.myapplication" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_qqsideslip" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="gaoyu.com.myapplication.sideslip.QQSideslipActivity"> <!--xmlns:gaoyu自定義命名空間 原有到res+包名--> <gaoyu.com.myapplication.sideslip.SlidingMenu_qq android:id="@+id/SlMenu_sideslip" android:layout_width="wrap_content" android:layout_height="fill_parent" gaoyu:rightPadding="100dp"> <LinearLayout android:layout_width="wrap_content" android:layout_height="match_parent" android:orientation="horizontal"> <include layout="@layout/sideslip_menu" /> <!--這個LinearLayout就是content--> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/sliding"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="onClick_sideslip_qq" android:text="切換菜單" /> </LinearLayout> </LinearLayout> </gaoyu.com.myapplication.sideslip.SlidingMenu_qq> </RelativeLayout>
菜單的布局
<?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:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_centerInParent="true"> <RelativeLayout android:layout_width="fill_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/iv_sideslip1" android:layout_width="50dp" android:layout_height="50dp" android:layout_marginTop="20dp" android:layout_marginBottom="20dp" android:layout_marginLeft="20dp" android:src="@drawable/icon"/> <TextView android:layout_centerVertical="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@+id/iv_sideslip1" android:layout_marginLeft="20dp" android:text="第一個item"/> </RelativeLayout> <RelativeLayout android:layout_width="fill_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/iv_sideslip2" android:layout_width="50dp" android:layout_height="50dp" android:layout_marginTop="20dp" android:layout_marginBottom="20dp" android:layout_marginLeft="20dp" android:src="@drawable/icon"/> <TextView android:layout_centerVertical="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@+id/iv_sideslip2" android:layout_marginLeft="20dp" android:text="第二個item"/> </RelativeLayout><RelativeLayout android:layout_width="fill_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/iv_sideslip3" android:layout_width="50dp" android:layout_height="50dp" android:layout_marginTop="20dp" android:layout_marginBottom="20dp" android:layout_marginLeft="20dp" android:src="@drawable/icon"/> <TextView android:layout_centerVertical="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@+id/iv_sideslip3" android:layout_marginLeft="20dp" android:text="第三個item"/> </RelativeLayout><RelativeLayout android:layout_width="fill_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/iv_sideslip4" android:layout_width="50dp" android:layout_height="50dp" android:layout_marginTop="20dp" android:layout_marginBottom="20dp" android:layout_marginLeft="20dp" android:src="@drawable/icon"/> <TextView android:layout_centerVertical="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@+id/iv_sideslip4" android:layout_marginLeft="20dp" android:text="第四個item"/> </RelativeLayout><RelativeLayout android:layout_width="fill_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/iv_sideslip5" android:layout_width="50dp" android:layout_height="50dp" android:layout_marginTop="20dp" android:layout_marginBottom="20dp" android:layout_marginLeft="20dp" android:src="@drawable/icon"/> <TextView android:layout_centerVertical="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@+id/iv_sideslip5" android:layout_marginLeft="20dp" android:text="第五個item"/> </RelativeLayout> </LinearLayout> </RelativeLayout>
定義view類
public class SlidingMenu_qq extends HorizontalScrollView {
private LinearLayout mWapper;
private ViewGroup mMenu;
private ViewGroup mContent;
//menu的寬度
private int mMenuWidth;
//屏幕的寬度(內(nèi)容區(qū)的寬度就是屏幕寬度)
private int mScreenWdith;
//菜單與右邊的距離50dp
private int mMenuRightPidding = 50;
//調(diào)用一次
private boolean once;
//標(biāo)識狀態(tài)
private boolean isOPen;
/**
* 未使用自定義屬性時調(diào)用
* 由于設(shè)置了attr所以...
*
* @param context
* @param attrs
*/
public SlidingMenu_qq(Context context, AttributeSet attrs) {
//調(diào)用三個參數(shù)的構(gòu)造方法
this(context, attrs, 0);
//獲取屏幕寬度(窗口管理器)
/*WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
//展示度量
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
mScreenWdith = outMetrics.widthPixels;
//把dp轉(zhuǎn)換成px
mMenuRightPidding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources().getDisplayMetrics());
*/
}
/**
* 當(dāng)實現(xiàn)自定義屬性時會執(zhí)行三個參數(shù)的方法
*
* @param context
* @param attrs
* @param defStyleAttr
*/
public SlidingMenu_qq(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//獲取自定義的屬性
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.SlidingMenu_qq, defStyleAttr, 0);
//自定義屬性個數(shù)
int n = a.getIndexCount();
for (int i = 0; i < n; i++) {
int attr = a.getIndex(i);
switch (attr) {
case R.styleable.SlidingMenu_qq_rightPadding:
//設(shè)置默認值是50dp
mMenuRightPidding = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources().getDisplayMetrics()));
break;
}
}
//釋放一下
a.recycle();
//獲取屏幕寬度(窗口管理器)
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
//展示度量
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
mScreenWdith = outMetrics.widthPixels;
}
/**
* new 一個TextView時傳一個上下文
*
* @param context
*/
public SlidingMenu_qq(Context context) {
//調(diào)用兩個參數(shù)的構(gòu)造方法
super(context, null);
}
/**
* 設(shè)置HorizontalScrollView子VIew的寬和高
* 設(shè)置HorizontalScrollView自己的寬和高
*
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//設(shè)置循環(huán)之調(diào)用一次
if (!once) {
//HorizontalScrollView 內(nèi)部只能有一個元素 所以直接get(0)就行就是那個Linerlayout mWapper
mWapper = (LinearLayout) getChildAt(0);
//獲取mWapper里的第一個元素menu
mMenu = (ViewGroup) mWapper.getChildAt(0);
//獲取mWapper里的第二個元素content
mContent = (ViewGroup) mWapper.getChildAt(1);
//菜單和內(nèi)容寬度
mMenuWidth = mMenu.getLayoutParams().width = mScreenWdith - mMenuRightPidding;
mContent.getLayoutParams().width = mScreenWdith;
//由于子對象被設(shè)置了,mWapper就先不用了
once = true;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
/**
* 通過設(shè)置偏移量 將menu隱藏
* @param changed
* @param l
* @param t
* @param r
* @param b
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
//限制多次調(diào)用
if (changed) {
//x為正滾動條向右 內(nèi)容向左(移動mMenuWidth 正好將菜單隱藏)
this.scrollTo(mMenuWidth, 0);
}
}
/**
* 判斷將菜單滑出來多少了
*
* @param ev
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_UP:
//隱藏在左邊的寬度
int scrollX = getScrollX();
if (scrollX >= mMenuWidth / 2) {
//scrollTo也行但是動畫效果不好 (隱藏)
this.smoothScrollTo(mMenuWidth, 0);
//代表菜單隱藏
isOPen = false;
} else {
this.smoothScrollTo(0, 0);
//表菜單打開
isOPen = true;
}
return true;
}
return super.onTouchEvent(ev);
}
/**
* 打開菜單
*/
public void openMenu() {
//已經(jīng)打開
if (isOPen) return;
this.smoothScrollTo(0, 0);
isOPen = true;
}
/**
* 關(guān)閉菜單
*/
public void closeMenu() {
//正在打開
if (!isOPen) return;
this.smoothScrollTo(mMenuWidth, 0);
isOPen = false;
}
/**
* 切換菜單
*/
public void toggle(){
if (isOPen){
closeMenu();
}else {
openMenu();
}
}
}
2.抽屜側(cè)滑(添加此方法)
/**
* 實現(xiàn)抽屜滑動
* l隱藏在左邊的寬度
* 后邊是變化梯度
*/
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
float scale = l*1.0f/mMenuWidth;//1~0梯度的值
//調(diào)用屬性動畫
ViewHelper.setTranslationX(mMenu,mMenuWidth*scale);
}
3.qq5.0側(cè)滑,實現(xiàn)這個方法
/**
* 實現(xiàn)仿qq5.0
* l等于隱藏在左邊的寬度(越來越?。?
* 后邊是變化梯度
*/
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
float scale = l * 1.0f / mMenuWidth;//1~0梯度的值
//調(diào)用屬性動畫
//菜單的縮放操作
float leftScale = 1.0f-scale*0.3f;
//透明度
float leftAlpha = 0.6f + 0.4f*(1-scale);
ViewHelper.setTranslationX(mMenu, mMenuWidth * scale*0.8f);
ViewHelper.setScaleX(mMenu,leftScale);
ViewHelper.setScaleY(mMenu,leftScale);
ViewHelper.setAlpha(mMenu,leftAlpha);
//內(nèi)容區(qū)域不斷縮小
float rightScale = 0.7f+0.3f*scale;
//橫向縱向縮放(不更改縮放中心點就全隱藏了)
ViewHelper.setPivotX(mContent,0);
ViewHelper.setPivotY(mContent,mContent.getHeight()/2);
ViewHelper.setScaleX(mContent,rightScale);
ViewHelper.setScaleY(mContent,rightScale);
}
更多學(xué)習(xí)內(nèi)容,可以點擊《Android側(cè)滑效果匯總》學(xué)習(xí)。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android解決viewpager嵌套滑動沖突并保留側(cè)滑菜單功能
- Android仿微信聯(lián)系人列表字母側(cè)滑控件
- Android_UI 仿QQ側(cè)滑菜單效果的實現(xiàn)
- Android 仿京東側(cè)滑篩選實例代碼
- android RecyclerView側(cè)滑菜單,滑動刪除,長按拖拽,下拉刷新上拉加載
- Android recyclerview實現(xiàn)拖拽排序和側(cè)滑刪除
- android的RecyclerView實現(xiàn)拖拽排序和側(cè)滑刪除示例
- Android側(cè)滑導(dǎo)航欄的實例代碼
- Android 側(cè)滑關(guān)閉Activity的實例
相關(guān)文章
Android實現(xiàn)RecyclerView添加分割線的簡便方法
這篇文章主要介紹了Android實現(xiàn)RecyclerView添加分割線的簡便方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07
解決Android中自定義DialogFragment解決寬度和高度問題
Android中自定義DialogFragment解決寬度和高度問題但是我們很多時候想把DialogFragment的高度固定,那么我們需要設(shè)置DialogFragment的高度,在Fragment的onResume()聲明周期方法中設(shè)置window的寬高即可2017-12-12
Android UI設(shè)計與開發(fā)之使用ViewPager實現(xiàn)歡迎引導(dǎo)頁面
這篇文章主要為大家詳細介紹了Android UI設(shè)計與開發(fā)之使用ViewPager實現(xiàn)歡迎引導(dǎo)頁面,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08
Android音頻開發(fā)之音頻采集的實現(xiàn)示例
本篇文章主要介紹了Android音頻開發(fā)之音頻采集的實現(xiàn)示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-04-04
Android開發(fā)中ProgressDialog簡單用法示例
這篇文章主要介紹了Android開發(fā)中ProgressDialog簡單用法,結(jié)合實例形式分析了Android使用ProgressDialog的進度條顯示與關(guān)閉、更新等事件響應(yīng)相關(guān)操作技巧,需要的朋友可以參考下2017-10-10
Kotlin中的handler如何避免內(nèi)存泄漏詳解
Handler,我們已經(jīng)相當(dāng)熟悉了,而且經(jīng)常用得不亦樂乎,但就是因為太熟悉了,才會偶爾被它反捅一刀,血流不止,下面這篇文章主要給大家介紹了關(guān)于Kotlin中handler如何避免內(nèi)存泄漏的相關(guān)資料,需要的朋友可以參考下。2017-12-12

