最近在做音乐播放软件,设计UI时,看了几款音乐播放软件,发现天天动听有个特效特别好。也就是点击主界面某个菜单按钮或手指向左滑动时,就可以将内容展现出来,而主界面被隐藏一部分。其效果图如下:
当点击右下角的按钮时,则会:
其实现原理为,在一个Activity的布局中需要有两部分,一个是菜单(menu)的布局,一个是(content)的布局。两个布局横向排列,菜单布局在左,内容布局在右。初始化时菜单布局完全显示在屏幕上,此时内容布局就会在屏幕右侧从而看不见。当点击菜单布局上的按钮时,就会时菜单布局向左偏移,以使得内容布局呈现在屏幕上。
其最终实现的效果如下:
当点击按钮后:
具体实现如下:
activity_main.xml:
[java] view plaincopy
<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:
[java] view plaincopy
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();
}
}
}
评论