自定义控件-侧边菜单SlidingMenu(滑动菜单)
生活随笔
收集整理的這篇文章主要介紹了
自定义控件-侧边菜单SlidingMenu(滑动菜单)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1.布局
?activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.example.slidemenu.MainActivity" > <com.example.slidemenu.SlideMenuandroid:id="@+id/sm"android:layout_width="match_parent"android:layout_height="match_parent" >? <!--?引入菜單布局,?索引為:?0?-->
? ? ? ??<include layout="@layout/slide_menu" />
? <!--?引入菜單布局,?索引為:?0?-->
<include layout="@layout/slide_content" /></com.example.slidemenu.SlideMenu></RelativeLayout>這個布局文件用到了自定義的ViewGroup對象com.example.slidemenu.SlideMenu,
繼承了ViewGroup類的控件時可以在其內部嵌套子控件。
slide_content.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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="horizontal"android:background="@drawable/top_bar_bg"android:gravity="center_vertical"><ImageViewandroid:id="@+id/iv" android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/main_back"/><TextView android:layout_width="1dp"android:layout_height="match_parent"android:background="@drawable/top_bar_divider"android:layout_margin="5dp"/><TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="新聞"android:textSize="30sp"android:textColor="#ffffff"/></LinearLayout><TextView android:layout_width="match_parent"android:layout_height="match_parent"android:textSize="30sp"android:text="!!!!!!!!!!!"android:gravity="center"/> </LinearLayout>slide_menu.xml
<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="240dp"android:layout_height="match_parent" ><LinearLayoutandroid:layout_width="240dp"android:layout_height="match_parent"android:background="@drawable/menu_bg"android:orientation="vertical" ><TextView android:text="新聞"android:drawableLeft="@drawable/tab_news"style="@style/SlideMenuStyle"/><TextView android:text="訂閱"android:drawableLeft="@drawable/tab_read"style="@style/SlideMenuStyle"/><TextView android:text="本地"android:drawableLeft="@drawable/tab_local"style="@style/SlideMenuStyle"/><TextView android:text="跟帖"android:drawableLeft="@drawable/tab_ties"style="@style/SlideMenuStyle"/><TextView android:text="圖片"android:drawableLeft="@drawable/tab_pics"style="@style/SlideMenuStyle"/><TextView android:text="話題"android:drawableLeft="@drawable/tab_ugc"style="@style/SlideMenuStyle"/><TextView android:text="投票"android:drawableLeft="@drawable/tab_vote"style="@style/SlideMenuStyle"/><TextView android:text="聚合閱讀"android:drawableLeft="@drawable/tab_focus"style="@style/SlideMenuStyle"/></LinearLayout></ScrollView>/res/values/styles.xml
<resources><style name="AppBaseTheme" parent="Theme.AppCompat.Light"></style><!-- Application theme. --><style name="AppTheme" parent="AppBaseTheme"></style> <!-- slideMenu style --><style name="SlideMenuStyle"><item name="android:layout_width">match_parent</item><item name="android:layout_height">wrap_content</item><item name="android:gravity">center_vertical</item><item name="android:textSize">18sp</item><item name="android:textColor">#ffffff</item><item name="android:background">@drawable/selector_slidemenuitem_bg</item><item name="android:padding">10dp</item><item name="android:drawablePadding">20dp</item><item name="android:onClick">click</item><item name="android:clickable">true</item></style></resources>res/drawable-hdpi/selector_slidemenuitem_bg.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" > <!-- @android:color/transparent為透明色 --><item android:drawable="@android:color/transparent" android:state_pressed="true"></item><item android:drawable="@color/slidemenu_press_bg" android:state_pressed="false"></item></selector>res/values/colors.xml
<?xml version="1.0" encoding="utf-8"?> <resources><color name="slidemenu_press_bg">#3333cccc</color> </resources>?
業務邏輯實現
?
自定義ViewGroup控件
?
?Android事件處理機制
--------------------------------------------------
自定義類SlideMenu繼承ViewGroup。該類作為自定義控件類。
SlideMenu.java
package com.example.slidemenu;import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.Scroller;public class SlideMenu extends ViewGroup {private int downX;// 按下時x軸的偏移量private int menuMeasuredWidth;int currentState = STATE_MAIN_VIEW;// 當前屏幕顯示的界面, 默認為: 主界面static final int STATE_MENU_VIEW = 0;// 菜單界面static final int STATE_MAIN_VIEW = 1;// 主界面// 利用這個對象做出滑動的動畫效果 Scroller scroller;public SlideMenu(Context context, AttributeSet attrs) {super(context, attrs);// TODO Auto-generated constructor stubscroller = new Scroller(context);}// 測量子節點的大小/*** widthMeasureSpec 填充屏幕 heightMeasureSpec 填充屏幕*/@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// TODO Auto-generated method stubsuper.onMeasure(widthMeasureSpec, heightMeasureSpec);// 調用子節點的measure方法,該方法實際是調用了子節點的onMeasure方法,測量子節點的大小// 測量菜單的寬和高. 寬: 240dip, 高: 填充屏幕View menuView = getChildAt(0);menuView.measure(menuView.getLayoutParams().width, heightMeasureSpec);// 測量主界面的寬和高. 寬: 填充屏幕, 高: 填充屏幕View mainView = getChildAt(1);mainView.measure(widthMeasureSpec, heightMeasureSpec);}// 分配空間// 因為slideMenu占滿了父元素,寬高與父元素相同// l:0// t:0// r:slideMenu的寬,也就是父元素的寬// b:slideMenu的高,也就是父元素的高 @Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {// TODO Auto-generated method stub// 主界面的位置放置在屏幕左上角View mainView = getChildAt(1);mainView.layout(l, t, r, b);// 把菜單的位置放置在屏幕的左側View menuView = getChildAt(0);menuMeasuredWidth = menuView.getMeasuredWidth();menuView.layout(-menuView.getMeasuredWidth(), t, 0, b);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {// 只有在橫著滑動時才可以攔截.switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:downX = (int) ev.getX();break;case MotionEvent.ACTION_MOVE:int moveX = (int) ev.getX();if (Math.abs(moveX - downX) > 10) {return true;}break;}return super.onInterceptTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent event) {// TODO Auto-generated method stubswitch (event.getAction()) {case MotionEvent.ACTION_DOWN:downX = (int) event.getX();break;case MotionEvent.ACTION_MOVE:int moveX = (int) event.getX();int offsetX = downX - moveX;// 判斷一下用戶手指滑動是否越界// 判斷給定當前的增量移動后, 是否能夠超出邊界.int scrollX = getScrollX();if (scrollX + offsetX < -menuMeasuredWidth) {// 當前超出了左邊界, 應該設置為在菜單的左邊界位置上.scrollTo(-menuMeasuredWidth, 0);} else if (scrollX + offsetX > 0) {// 當前超出了右邊界, 應該設置為0scrollTo(0, 0);} else {scrollBy(offsetX, 0);}downX = moveX;break;case MotionEvent.ACTION_UP:// 獲取菜單寬度的一半int center = -menuMeasuredWidth / 2;scrollX = getScrollX();// 當前屏幕左上角的值if (scrollX < center) {currentState = STATE_MENU_VIEW;refreshViewState();} else {currentState = STATE_MAIN_VIEW;refreshViewState();}break;}return true;}// 松手時根據滑動進度,讓mScrollX復位/*** 根據currentScreen變量來切換屏幕顯示*/private void refreshViewState() {// TODO Auto-generated method stubint startX = getScrollX();// 開始的位置int dx = 0;// 增量值 = 目的地位置 - 開始的位置;if (currentState == STATE_MAIN_VIEW) {dx = 0 - startX;} else if (currentState == STATE_MENU_VIEW) {dx = -menuMeasuredWidth - startX;}int duration = Math.abs(dx) * 10;if (duration > 1600) {duration = 1600;}// arg0:滑動的開始坐標// arg1:滑動的距離scroller.startScroll(startX, 0, dx, 0, duration);// 只要調用invalidate,那么computeScroll方法就會調用// 刷新當前控件, 會引起onDraw方法的調用.invalidate();// -> drawChild -> view.draw -> view.computeScroll }@Overridepublic void computeScroll() {// scroller不會去改變mScrollX的值,它只是幫你計算出你應該把mScrollX的值變為多少// 判斷動畫是否結束,如果時間到了,那么結束了,返回false,如果時間未到,返回trueif (scroller.computeScrollOffset()) {// 當前mScrollX應該變為多少,這個返回值是startX+應該位移的距離/** scroller .startScroll(0 , 0 , 1000, 0,100);* * 當時間過去了1毫秒時,屏幕應該移動10像素 當時間過去了10毫秒時,屏幕應該移動100像素 例如:* 3點10分50000毫秒,調用那個了scroller.startScroll(0 , 0 , 1000, 0,100);* 3點10分50010毫秒,調用那個了scroller.getcurrx(),返回100* 3點10分50050毫秒,調用那個了scroller.getcurrx(),返回500*/int currX = scroller.getCurrX();scrollTo(currX, 0);invalidate();// 在觸發當前方法, 相當于遞歸. }}/*** 是否顯示菜單* * @return true 顯示菜單, false 不顯示*/public boolean isShowMenu() {return currentState == STATE_MENU_VIEW;}/*** 隱藏菜單*/public void hideMenuView() {currentState = STATE_MAIN_VIEW;refreshViewState();}/*** 顯示菜單*/public void showMenuView() {currentState = STATE_MENU_VIEW;refreshViewState();} }MainActivity.xml
package com.example.slidemenu;import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast;public class MainActivity extends ActionBarActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_main);final SlideMenu sm = (SlideMenu) findViewById(R.id.sm);ImageView iv = (ImageView) findViewById(R.id.iv);iv.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// 判斷當前狀態if (sm.isShowMenu()) {// 是菜單界面, 切換到主界面 sm.hideMenuView();} else {// 是主界面, 應該把菜單顯示出來 sm.showMenuView();}}});}public void click(View v) {Toast.makeText(this, ((TextView) v).getText(), 0).show();}}?
轉載于:https://www.cnblogs.com/crazyzx/articles/5545970.html
總結
以上是生活随笔為你收集整理的自定义控件-侧边菜单SlidingMenu(滑动菜单)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PAT 甲级 1027 Colors i
- 下一篇: UNIX环境高级编程 文件I/O