Android自定義View 仿QQ側滑菜單的實現(xiàn)代碼
先看看QQ的側滑效果
分析一下
先上原理圖(不知道能否表達的清楚 ==)
-首先這里使用了 Android 的HorizontalScrollView
水平滑動布局作為容器,當然我們需要繼承它自定義一個側滑視圖
- 這個容器里面有一個父布局(一般用LinerLayout,本demo用的是),這個父布局里面有且只有兩個子控件(布局),初始狀態(tài)菜單頁的位置在Y軸上存在偏移這樣可以就可以形成主頁疊在菜單頁的上方的視覺效果;然后在滑動的過程程中 逐漸修正偏移,最后菜單頁和主頁并排排列。原理搞清了實現(xiàn)起來就不是事兒了……
具體實現(xiàn)
布局代碼
<fierce_luk.com.sideslipviewdemo2.SideslipView android:id="@+id/my_veiw" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="none" luk:leftPanding="200dp"> <!--如果菜單在左邊直接用 LinearLayout--> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <TextView android:id="@+id/image2" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@mipmap/homepage" android:gravity="center" android:tag="0" android:text="菜單" android:textColor="@color/colorAccent" android:textSize="60sp" /> <TextView android:id="@+id/image1" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/color1" android:gravity="center" android:tag="1" android:text="主頁面" android:textColor="@color/colorAccent" android:textSize="60sp" /> </FrameLayout> <!--<fragment--> <!--android:name="com.luk.bluetoothapp.fragment.MyBluetoothDevice"--> <!--android:layout_width="match_parent"--> <!--android:layout_height="match_parent"--> <!--android:tag="1" />--> <!--<fragment--> <!--android:name="com.luk.bluetoothapp.fragment.HomeFragment"--> <!--android:layout_width="match_parent"--> <!--android:layout_height="match_parent"--> <!--android:tag="0" />--> </fierce_luk.com.sideslipviewdemo2.SideslipView>
自定義的側滑視圖
最核心的部分
public class SideslipView extends HorizontalScrollView { private int mScreenWidth;//屏幕寬度 private int mMenuLeftPadding; private int mBluetoothWidth;//菜單的寬度 private int mHalfMenuWidth; View home; View bluetooth; protected boolean isOpen; protected boolean isFirst = true; public SideslipView(Context context) { // super 改 this this(context, null); } public SideslipView(Context context, AttributeSet attrs) { // super 改 this this(context, attrs, 0); } public SideslipView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //測量屏幕寬度 WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics metrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(metrics); mScreenWidth = metrics.widthPixels; // mScreenWidth = context.getResources().getDisplayMetrics().widthPixels; Log.e("TAG", "MyScrollView: mScreenWidth" + mScreenWidth); //獲取 自定義的屬性值 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyScrollView); int n = a.length(); for (int i = 0; i < n; i++) { int arrt = a.getIndex(i); switch (arrt) { case R.styleable.MyScrollView_leftPanding: mMenuLeftPadding = (int) a.getDimension(R.styleable.MyScrollView_leftPanding, 0); break; default: break; } } Log.e("TAG", "MyScrollView: mMenuLeftPadding" + mMenuLeftPadding); a.recycle(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (isFirst) { //獲取子布局 并設置寬度 //如果菜單在左邊 用LinearLayout就行 // LinearLayout layout = (LinearLayout) this.getChildAt(0); /**此處因為 把側邊拉出頁面設置在了右邊 所有用 FrameLayout * 不然在設置偏移量時 隱藏的側邊菜單會跑到主頁面的上面*/ FrameLayout layout = (FrameLayout) this.getChildAt(0); home = layout.getChildAt(1); bluetooth = layout.getChildAt(0); LayoutParams params = new LayoutParams(mBluetoothWidth, getResources().getDisplayMetrics().heightPixels); params.setMargins(mScreenWidth, 0, 0, 0); bluetooth.setLayoutParams(params); mBluetoothWidth = mScreenWidth - mMenuLeftPadding; home.getLayoutParams().width = mScreenWidth; bluetooth.getLayoutParams().width = mBluetoothWidth; mHalfMenuWidth = mBluetoothWidth / 2; isFirst = false; } 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); //首先隱藏 Bluetooth if (changed) this.scrollTo(0, mBluetoothWidth); } Animation anim; @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_UP: int scrollX = getScrollX(); if (scrollX >= mHalfMenuWidth) { Log.e("TAG", "===="); this.smoothScrollTo(mBluetoothWidth, 0); isOpen = true; } else { this.smoothScrollTo(0, 0); isOpen = false; } //必須消耗事件 return true; } return super.onTouchEvent(ev); //return true; } /** * 打開菜單欄 */ protected void openMenu() { if (isOpen) return; this.smoothScrollTo(mBluetoothWidth, 0); isOpen = true; } /** * 關閉菜單欄 */ protected void closeMenu() { if (!isOpen) return; this.smoothScrollTo(0, 0); isOpen = false; } /** * 按鈕切換菜單 */ public void toggleMenu() { if (isOpen) closeMenu(); else openMenu(); } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); //此處 l 起始值為零(沒有偏移) Log.e("TAG", "l=" + l + " t=" + t); Log.e("TAG", "oldl=" + oldl + " oldt=" + oldt); // scale 在 1 到 0 之間 float scale = l * 1.0f / mBluetoothWidth; /** * 抽屜式側滑 * scaleLeft 從默認偏移量到偏移量 為零 *實現(xiàn) * */ float scaleLeft = 0.4f - 0.4f * scale; /**設置 X 軸方向的偏移量**/ ViewHelper.setTranslationX(bluetooth, -(mBluetoothWidth * scaleLeft)); Log.e("TAG", "mBluetoothWidth+" + mBluetoothWidth); Log.e("TAG", "=============" + mBluetoothWidth * scale + "scale" + scale); /* *//**設置縮放時的 軸心點**//* //此處軸心為右邊界的中點 ViewHelper.setPivotY(home, mScreenWidth); ViewHelper.setPivotX(home, home.getHeight() / 2); *//**設置 XY軸方向的 縮放動畫(從 1 到 0.9)**//* float pivoXY = 1 - 0.4f * scale; ViewHelper.setScaleX(home, pivoXY); ViewHelper.setScaleY(home, pivoXY);*/ /* *//**設置透明度**//* //從 1 到 0.6; float alpha = 1 - 0.4f * scale; ViewHelper.setAlpha(home, alpha);*/ } }
擴展
添加之定義屬性 讓用戶配置菜單距離右邊的邊距的值;
首先在values文件夾下新建一個attr.xml,寫入以下內(nèi)容:
<resources> <declare-styleable name="MyScrollView"> <attr name="rightPanding" format="dimension" /> <attr name="leftPanding" format="dimension" /> </declare-styleable> </resources>
在布局里設置邊距
<fierce_luk.com.sideslipviewdemo2.SideslipView android:id="@+id/my_veiw" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="none" luk:leftPanding="200dp">
其他的就不贅述了,看看效果
- 源碼下載Demo源碼點擊下載
總結
以上所述是小編給大家介紹的Android自定義View 仿QQ側滑菜單的實現(xiàn)代碼,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關文章
Android 使用Glide加載網(wǎng)絡圖片等比例縮放的實現(xiàn)方法
這篇文章主要介紹了Android 使用Glide加載網(wǎng)絡圖片等比例縮放的實現(xiàn)方法,需要的朋友可以參考下2018-08-08Android使用BottomTabBar實現(xiàn)底部導航頁效果
這篇文章主要介紹了Android使用BottomTabBar實現(xiàn)底部導航頁效果,本文通過實例代碼結合文字說明的形式給大家介紹的非常詳細,需要的朋友參考下吧2018-03-03Android中自定義PopupWindow實現(xiàn)彈出框并帶有動畫效果
這篇文章主要介紹了Android中自定義PopupWindow實現(xiàn)彈出框并帶有動畫效果的相關資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-09-09Android 圖片存入系統(tǒng)相冊更新顯示實例詳解
這篇文章主要介紹了Android 圖片存入系統(tǒng)相冊更新顯示實例詳解的相關資料,需要的朋友可以參考下2017-06-06Android RecycleView實現(xiàn)Item拖拽效果
RecyclerView是Android一個更強大的控件,其不僅可以實現(xiàn)和ListView同樣的效果,還有優(yōu)化了ListView中的各種不足。本文將介紹通過RecyclerView實現(xiàn)Item拖拽效果以及拖拽位置保存,感興趣的可以參考一下2022-01-01Android6.0編程實現(xiàn)雙向通話自動錄音功能的方法詳解
這篇文章主要介紹了Android6.0編程實現(xiàn)雙向通話自動錄音功能的方法,結合實例形式分析了Android錄音功能的原理、實現(xiàn)技巧與相關注意事項,需要的朋友可以參考下2017-07-07