今天咱們來實作一個側滑效果,簡單而又輕巧。大家下載下傳源碼,直接參照源碼,使用非常簡單。我就不上傳github,如果大家有需要的話,請在下面留言,給大家打包成類庫。
大家知道側滑菜單非常流行,包括現在的QQ側滑菜單,酷狗的縮放動畫的側滑菜單,都是非常棒的。這個側滑控件還是能滿足大多數實際項目需求的。如果說簡單而又有内涵,是不是霸氣呢?我們現在就開始學習如何去自己寫一個。效果圖如下。
先帶大家了解一下題外内容。大家知道什麼是子節點,父節點嗎?知道的話,本段可以略過了。其實這個說一下,是為了後面做鋪墊的。在DDMS工具中,有個工具叫做Hierarchy。
,這個工具在哪呢?其實就在我們的DDMS界面。
大家看右圖的右側,就是這個界面的布局節點。節點的英文單詞叫做node。
ok,了解了上面的内容之後,咱們就可以正式開始我們的側滑項目了。
我們要實作側滑,那麼我們該繼承哪個類呢?其實大家可以從View繼承,不過太麻煩了。那麼我們可以繼承一個已經實作了滾動的控件HorizontalScrollView。
我們先來看下側滑的實質是什麼樣的,請允許我自畫一個略顯醜陋的圖吧。
最外層其實就是一個HorizontalScrollView,裡面包含了Menu布局界面和主界面。
第一步:先寫一個類繼承自HorizontalScrollView。
注意:實作第二個帶有2個參數的構造方法,為什麼實作第二個呢?當我們不需要定義新的屬性的時候,我們隻需要實作帶有2個參數的構造方法。
public class SlidingMenu extends HorizontalScrollView{
public SlidingMenu(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
第二步:編寫main.xml(主界面),menu.xml(菜單頁),以及HorizontalScrollView自身的布局界面
main.xml就是一個圖檔,具體的大家根據項目實際寫。menu菜單代碼如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@drawable/background">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="50dp"
android:layout_marginLeft="50dp"
>
<ImageView
android:layout_width="45dp"
android:layout_height="45dp"
android:src="@drawable/weibo"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:gravity="center"
android:text="menu1"
android:textSize="20sp" />
</LinearLayout>
<!--此處省略三個item,和上面的那個LinearLayout内容相似,大家可以把文字和圖檔替換掉就可以了-->
</LinearLayout>
随後,我們可以把這兩個界面插入到HorizontalScrollView自身的布局中去,也就是我們項目自動生成的activity_main.xml布局。
<com.example.slidingmenu.widget.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="match_parent"
android:scrollbars="none"
android:fadingEdge="none"
>
<!--上面的最後2行是為了去除滾動條和陰影效果-->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<include layout="@layout/menu"/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/main"
></LinearLayout>
</LinearLayout>
</com.example.slidingmenu.widget.SlidingMenu>
大家注意了,menu菜單僅僅是左邊的,還有部分顯示的是主界面的。這個在後面的代碼裡會實作。
第三步:完善SlidingMenu類,首先得到螢幕寬度
我們首先得到螢幕的寬度。為了後面的計算Menu菜單和主界面布局寬度作為鋪墊。
public class SlidingMenu extends HorizontalScrollView{
private ViewGroup mMenuLayout;//菜單布局界面
private ViewGroup mMainLayout;//主布局界面
private int mScreenWidth;//螢幕寬度
private int mPaddingRight = 100;//右邊距大小
private float downX;//按下時候的橫坐标
private float upX;//手指松開時候的橫坐标
private int mMenuWidth;//菜單界面寬度
/**
* @param context
* @param attrs
*/
public SlidingMenu(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
DisplayMetrics displayMetrics = new DisplayMetrics();
display.getMetrics(displayMetrics);
mScreenWidth = displayMetrics.widthPixels;
}
}
在拿到了螢幕的寬度之後,我們就可以來計算menu菜單界面和主界面分别在螢幕中的寬度了。
我們很容易想到,總的寬度就是menu菜單加上主界面的寬度。我們可以清楚地看到menu菜單的寬度有個padding邊距。這個右邊距我設定的是100。感覺還可以。
menu菜單頁寬度 = 螢幕寬度 - 右邊距
主界面寬度 = 螢幕寬度
上面式子大家應該看懂了吧!看懂了就好辦。
第四步:計算munu菜單和主界面菜單寬度。重寫onMeasure方法
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
LinearLayout layout = (LinearLayout)getChildAt(0);//得到最外層的LinearLayout布局檔案
//菜單布局
mMenuLayout = (ViewGroup) layout.getChildAt(0);
//主界面布局
mMainLayout = layout.getChildAt(1);
mMenuWidth = mScreenWidth - mPaddingRight;//菜單寬度
//設定菜單寬度
mMenuLayout.getLayoutParams().width = mMenuWidth;
//主布局寬度
mMainLayout.getLayoutParams().width = mScreenWidth;
}
getChildAt(int index)這個方法可以得到子節點,這裡我們先得到父LinearLayout布局,再根據getChildAt方法得到子view的布局。
可能大家會問,為什麼要這樣得到2個view呢,其實ViewGroup是view的子類。通過上面的DDMS中的樹形圖可以很好的明白。我們可以知道這2個LinearLayout是同一級别的,都是在父LinearLayout節點的下面。
這樣我們就實作了上圖的效果,可實際上效果是這樣嗎?不好意思,到這裡,我們雖然可以滑動,但是滑動起來可能不流暢。
怎麼辦呢?
這個時候,我們需要實作手勢動作的監聽。
當我們向右邊滑動的時候,主布局要隐藏大半部分,隻留下了右邊距寬度的可視,其他的都在不可視範圍内。并不代表消失。
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = ev.getX();//按下的橫坐标
break;
case MotionEvent.ACTION_UP:
upX = ev.getX();//松開的橫坐标
float d = upX - downX;
if(d<0){
//往左移動
this.smoothScrollTo(mMenuWidth, 0);
}else{
//向右滑動
this.smoothScrollTo(0, 0);
}
return true;
default:
break;
}
return super.onTouchEvent(ev);
}
第四步:初始化布局
最後,我們需要初始化渲染布局位置。請注意了,初始化的時候我們的menu菜單完全隐藏,隻留下主界面布局可視。是以我們需要重寫onLayout方法。
/*
* (non-Javadoc)
* @see android.widget.HorizontalScrollView#onLayout(boolean, int, int, int, int)
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
this.smoothScrollTo(mMenuWidth, 0);//初始化布局界面
}
看到這裡,相信大家都已經學會了如何實作側滑了。大家覺得有問題的話可以留言哦!下篇會對SlidingMenu進行縮放動畫擴充及更精确地判斷監聽手勢。敬請期待!
源碼下載下傳