iOS及Android上的瑞士军刀界面很是新颖,也很便捷。很多应用采用了该设计,例如QQ,凤凰新闻客户端等。今天介绍一下通过自定义HorizontalScrollView类的方法实现瑞士军刀界面。
依赖jar包
NineOldAndroids.jar
思路
●使用HorizontalScrollView布局,左侧为Menu,右侧为Content;
自定义HorizontalScrollView,使之监听Action_UP事件,进行Menu的显示和隐藏;
●menu隐藏在抽屉正下方
属性动画:改变拖动时,
调用动画时机:ACTION_MOVE==>覆写View类的onScrollChanged()方法
●菜单及内容区域的缩放和透明度变化
拖动时 scale:1.0-0
menu透明度变化:0.7-1.0
menu缩放变化:0.7-1.0
content缩放变化:1.0-0.7【注意默认缩放中心会影响实际效果,需要设置缩放中心】
效果图
核心代码
自定义HorizontalScrollView类SlidingMenu
public class SlidingMenu extends HorizontalScrollView { private LinearLayout mWrapper; private ViewGroup mMenu; private ViewGroup mContent; private int menuWidth; private int slidingMenuPadding; private int screenWidth; private boolean once; private boolean isOpen; public SlidingMenu(Context context, AttributeSet attr) { super(context, attr); DisplayMetrics dm = new DisplayMetrics(); WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); wm.getDefaultDisplay().getMetrics(dm); screenWidth = dm.widthPixels; slidingMenuPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 80, context.getResources().getDisplayMetrics()); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { this.scrollTo(menuWidth, 0); super.onLayout(changed, l, t, r, b); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (!once) { mWrapper = (LinearLayout) getChildAt(0); mMenu = (ViewGroup) mWrapper.getChildAt(0); mContent = (ViewGroup) mWrapper.getChildAt(1); menuWidth = mMenu.getLayoutParams().width = screenWidth - slidingMenuPadding; mContent.getLayoutParams().width = screenWidth; once = true; } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_UP: int scrollX = getScrollX(); if (scrollX >= menuWidth / 2) { this.smoothScrollTo(menuWidth, 0); isOpen = false; } else { this.smoothScrollTo(0, 0); isOpen = true; } return true; } return super.onTouchEvent(ev); } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); float scale = l * 1.0f / menuWidth; float rightScale = 0.7f + scale * 0.3f; float leftScale = 1.0f - scale * 0.3f; float leftAlpha = 1.0f - scale * 0.3f; ViewHelper.setTranslationX(mMenu, l * 0.5f); ViewHelper.setScaleX(mMenu, leftScale); ViewHelper.setScaleY(mMenu, leftScale); ViewHelper.setAlpha(mMenu, leftAlpha); ViewHelper.setPivotX(mContent, 0); ViewHelper.setPivotY(mContent, mContent.getHeight() / 2); ViewHelper.setScaleX(mContent, rightScale); ViewHelper.setScaleY(mContent, rightScale); } public void trigger() { if (isOpen) { closeMenu(); isOpen = false; } else { openMenu(); isOpen = true; } } private void openMenu() { if (isOpen) return; this.smoothScrollTo(0, 0); } private void closeMenu() { if (!isOpen) return; this.smoothScrollTo(menuWidth, 0); }
布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/leaf" > <com.example.dialogtest.SlidingMenu android:id="@+id/menu_id" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="none" > <LinearLayout android:layout_width="wrap_content" android:layout_height="match_parent" android:orientation="horizontal" > <include layout="@layout/sliding_menu" /> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/apple" > <Button android:layout_height="wrap_content" android:layout_width="wrap_content" android:background="@drawable/title_bar_menu" android:onClick="showMenu" /> </LinearLayout> </LinearLayout> </com.example.dialogtest.SlidingMenu> </RelativeLayout