最近在做音乐播放软件,设计UI时,看了几款音乐播放软件,发现天天动听有个特效特别好。也就是点击主界面某个菜单按钮或手指向左滑动时,就可以将内容展现出来,而主界面被隐藏一部分。其效果图如下:
当点击右下角的按钮时,则会:
其实现原理为,在一个Activity的布局中需要有两部分,一个是菜单(menu)的布局,一个是(content)的布局。两个布局横向排列,菜单布局在左,内容布局在右。初始化时菜单布局完全显示在屏幕上,此时内容布局就会在屏幕右侧从而看不见。当点击菜单布局上的按钮时,就会时菜单布局向左偏移,以使得内容布局呈现在屏幕上。
其最终实现的效果如下:
当点击按钮后:
具体实现如下:
activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" tools:context=".MainActivity" > <LinearLayout android:id="@+id/menu" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#b2d235" > <Button android:id="@+id/button1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="打开"/> </LinearLayout> <LinearLayout android:id="@+id/content" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/right"> </LinearLayout> </LinearLayout>
MainActivity.java:
package com.ye_yun_lin.mytest; import android.os.AsyncTask; import android.os.Bundle; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.view.WindowManager; import android.widget.Button; import android.widget.LinearLayout; import android.app.Activity; import android.content.Context; public class MainActivity extends Activity implements OnTouchListener{ private Button backButton; private boolean isMenuVisible; public static final int SNAP_VELOCITY = 200; private int screenWidth; private int leftEdge; private int rightEdge = 0; private int menuPadding = 180; private View content; private View menu; private LinearLayout.LayoutParams menuParams; private LinearLayout.LayoutParams contentParams; private float xDown; private float xMove; private float xUp; private VelocityTracker mVelocityTracker; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initvalues(); menu.setOnTouchListener(this); backButton=(Button)findViewById(R.id.button1); backButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { menuParams.leftMargin=leftEdge; menu.setLayoutParams(menuParams); isMenuVisible=false; } }); } @SuppressWarnings("deprecation") private void initvalues(){ WindowManager window = (WindowManager) getSystemService(Context.WINDOW_SERVICE); screenWidth = window.getDefaultDisplay().getWidth(); menu=findViewById(R.id.menu); content=findViewById(R.id.content); menuParams=(LinearLayout.LayoutParams)menu.getLayoutParams(); contentParams=(LinearLayout.LayoutParams)content.getLayoutParams(); menuParams.width=screenWidth; contentParams.width=menuPadding; menuParams.leftMargin=rightEdge; leftEdge=-menuPadding; } @Override public boolean onTouch(View v, MotionEvent event) { createVelocityTracker(event); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: xDown = event.getRawX(); break; case MotionEvent.ACTION_MOVE: xMove = event.getRawX(); int distanceX = (int) (xMove - xDown); System.out.println("------->>"+distanceX); if (isMenuVisible) { menuParams.leftMargin = distanceX; } else { menuParams.leftMargin = leftEdge + distanceX; } if (menuParams.leftMargin < leftEdge) { menuParams.leftMargin = leftEdge; } else if (menuParams.leftMargin > rightEdge) { menuParams.leftMargin = rightEdge; } menu.setLayoutParams(menuParams); break; case MotionEvent.ACTION_UP: xUp = event.getRawX(); if (wantToShowMenu()) { if (shouldScrollToMenu()) { scrollToMenu(); } else { scrollToContent(); } } else if (wantToShowContent()) { if (shouldScrollToContent()) { scrollToContent(); } else { scrollToMenu(); } } recycleVelocityTracker(); break; } return true; } private void createVelocityTracker(MotionEvent event) { if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } mVelocityTracker.addMovement(event); } private int getScrollVelocity() { mVelocityTracker.computeCurrentVelocity(1000); int velocity = (int) mVelocityTracker.getXVelocity(); return Math.abs(velocity); } private void recycleVelocityTracker() { mVelocityTracker.recycle(); mVelocityTracker = null; } private boolean wantToShowContent() { return xUp - xDown < 0; } private boolean wantToShowMenu() { return xUp - xDown > 0; } private boolean shouldScrollToMenu() { return xUp - xDown > menuPadding || getScrollVelocity() > SNAP_VELOCITY; } private boolean shouldScrollToContent() { return xDown - xUp > menuPadding || getScrollVelocity() > SNAP_VELOCITY; } private void scrollToMenu() { new ScrollTask().execute(30); } private void scrollToContent() { new ScrollTask().execute(-30); } class ScrollTask extends AsyncTask<Integer, Integer, Integer> { @Override protected Integer doInBackground(Integer... speed) { int leftMargin = menuParams.leftMargin; while (true) { leftMargin = leftMargin + speed[0]; if (leftMargin > rightEdge) { leftMargin = rightEdge; break; } if (leftMargin < leftEdge) { leftMargin = leftEdge; break; } publishProgress(leftMargin); sleep(20); } if (speed[0] > 0) { isMenuVisible = true; } else { isMenuVisible = false; } return leftMargin; } @Override protected void onProgressUpdate(Integer... leftMargin) { menuParams.leftMargin = leftMargin[0]; menu.setLayoutParams(menuParams); } @Override protected void onPostExecute(Integer leftMargin) { menuParams.leftMargin = leftMargin; menu.setLayoutParams(menuParams); } } private void sleep(long millis) { try { Thread.sleep(millis); } catch (InterruptedException e) { e.printStackTrace(); } } }
最终效果如下:
---->