互联网有二家大公司做的产品是最好的,至少个人是这么认为的,一个是腾讯,一个是网易,今天就使用android提供一个强大的类ViewDragHelper来实现QQ主界面这个效果,不要告诉我你不知道这个效果,除非你不用qq,那么基本判断你还是生活在老毛的时代,
在做这个效果中遇到一个问题就是不能让菜单的layout移动,当时是这么写的
<span style="font-size:18px;">@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
if(child==mainView){
if(left<=0) left=0;
if(left>moveRange)left=moveRange;
}
return left;
}</span>
<span style="font-size:18px;">想在这个方法中做些判断,如果滑动的是菜单的layout就怎么样,后来发现这样不行,于是乎:就想到了在onViewPositionChanged()方法中困定死这个菜单layout的位置,
menuView.layout(0, 0, menuView.getMeasuredWidth(), menuView.getMeasuredHeight());</span>
<span style="font-size:18px;">下面图是对这个总结:</span>
<img src="https://img-blog.youkuaiyun.com/20160309171349856?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
<span style="font-size:18px;">现在把代码全部贴上来:</span>
<span style="font-size:18px;">MainActivity.java
</span>
<span style="font-size:18px;"><pre name="code" class="html">package com.slidmenu;
import com.slidmenu.view.MainViewGroup;
import com.slidmenu.view.SildMenuView;
import com.slidmenu.view.SildMenuView.onDragSlideMenuListener;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.LayoutParams;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends Activity {
private SildMenuView slidmenu;
private MainViewGroup ll_main_root;
private ImageView iv_head;
private ListView menu_listview,main_listview;
private String[] menu_contents = {"体育新闻","今日头条","娱乐新闻","民生新闻","小品","相声","推荐"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv_head = (ImageView) findViewById(R.id.iv_head);
ll_main_root = (MainViewGroup) findViewById(R.id.ll_main_root);
slidmenu = (SildMenuView) findViewById(R.id.slidmenu);
menu_listview = (ListView) findViewById(R.id.menu_listview);
main_listview = (ListView) findViewById(R.id.main_listview);
main_listview.setAdapter(new MainAdapter());
menu_listview.setAdapter(new MenuAdapter());
ll_main_root.setSildMenuView(slidmenu);
//主界面上面的小人头
iv_head.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if(slidmenu.isOpen()){
slidmenu.close();
}else{
slidmenu.open();
}
}
});
slidmenu.setListener(new onDragSlideMenuListener() {
@Override
public void open() {
}
@Override
public void close() {
}
});
}
class MainAdapter extends BaseAdapter{
@Override
public int getCount() {
return 20;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv = new TextView(getApplicationContext());
tv.setText("qq号---123456789");
tv.setGravity(Gravity.CENTER);
tv.setTextColor(Color.BLACK);
AbsListView.LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,80);
tv.setLayoutParams(params);
return tv;
}
}
class MenuAdapter extends BaseAdapter{
@Override
public int getCount() {
// TODO Auto-generated method stub
return menu_contents.length;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv = new TextView(getApplicationContext());
tv.setText(menu_contents[position]);
tv.setGravity(Gravity.CENTER_VERTICAL);
tv.setTextColor(Color.BLUE);
AbsListView.LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,80);
tv.setLayoutParams(params);
return tv;
}
}
//处理当slidemenu是打开状态的时候按返回键 是关闭状态 否则就退出栈
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode==KeyEvent.KEYCODE_BACK){
if(slidmenu.isOpen()){
slidmenu.close();
return false;
}
}
return super.onKeyDown(keyCode, event);
}
}
</span>
MainViewGroup.java 自定义内容区layout
<span style="font-size:18px;"><pre name="code" class="html">package com.slidmenu.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.LinearLayout;
public class MainViewGroup extends LinearLayout {
private SildMenuView sildMenuView ;
public MainViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public MainViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MainViewGroup(Context context) {
super(context);
}
public void setSildMenuView(SildMenuView sildMenuView){
this.sildMenuView = sildMenuView;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if(sildMenuView!=null&&sildMenuView.isOpen()){//打开状态
if(event.getAction()==MotionEvent.ACTION_UP){
sildMenuView.close();
}
return true;
}
return super.onTouchEvent(event);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if(sildMenuView!=null&&sildMenuView.isOpen()){//打开状态
return true;//自己处理
}
return super.onInterceptTouchEvent(ev);
}
}
</span>
SildMenuView.java
<span style="font-size:18px;"><pre name="code" class="html">package com.slidmenu.view;
import com.nineoldandroids.animation.FloatEvaluator;
import com.nineoldandroids.view.ViewHelper;
import android.content.Context;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.support.v4.widget.ViewDragHelper.Callback;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
public class SildMenuView extends FrameLayout {
private static final String TAG = SildMenuView.class.getSimpleName();
private ViewDragHelper mViewHelper;
private View menuView;
private View mainView;
private int moveRange;
private FloatEvaluator floatEvaluator;
private onDragSlideMenuListener listener;
public enum state {OPEN,CLOSE};
state currentState = state.CLOSE;
public void setListener(onDragSlideMenuListener listener) {
this.listener = listener;
}
public SildMenuView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public SildMenuView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public SildMenuView(Context context) {
this(context,null);
}
private void init() {
floatEvaluator = new FloatEvaluator();
mViewHelper = ViewDragHelper.create(this, new Callback() {
@Override
public boolean tryCaptureView(View arg0, int arg1) {
return true;
}
/**
* 主要处理的是mainview左右滑动的边界限制
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
if(child==mainView){
if(left<=0) left=0;
if(left>moveRange)left=moveRange;
}
return left;
}
//表示竖直方向不移动
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
return 0;
}
@Override
public int getViewHorizontalDragRange(View child) {
return moveRange;
}
@Override
public int getViewVerticalDragRange(View child) {
return super.getViewVerticalDragRange(child);
}
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
if(changedView==menuView){
menuView.layout(0, 0, menuView.getMeasuredWidth(), menuView.getMeasuredHeight());
int mainLeft = mainView.getLeft()+dx;
if(mainLeft>moveRange){
mainLeft=moveRange;
}
mainView.layout(mainLeft, mainView.getTop()+dy, mainView.getRight()+dx, mainView.getBottom()+dy);
//实时计算mainview移动的百分比
}
float movePercent =(float) mainView.getLeft()/moveRange;
setAnim(movePercent);
Log.e(TAG, "movePercent--->"+movePercent);
if(movePercent==0&¤tState!=state.CLOSE){
if(listener!=null){
currentState=state.CLOSE;
listener.close();
}
}
if(movePercent==1&¤tState!=state.OPEN){
if(listener!=null){
currentState=state.OPEN;
listener.open();
}
}
}
/**
* 实现当收松开的状态 mainView 如果滑动到大于menu宽的一半 mainView,menuView就全部显示,
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
if(mainView!=null){
if(mainView.getLeft()>moveRange/2){//向右
smoothSlideViewTo(mainView, moveRange, 0);
}else{//向左
smoothSlideViewTo(mainView, 0, 0);
}
}
}
});
}
public void close(){
smoothSlideViewTo(mainView, 0, 0);
}
public void open(){
smoothSlideViewTo(mainView, moveRange, 0);
}
protected void setAnim(float movePercent) {
//1表示起始值 0.9表示最小缩放到的值
ViewHelper.setScaleX(mainView, floatEvaluator.evaluate(movePercent,1f,0.9f));
ViewHelper.setScaleY(mainView, floatEvaluator.evaluate(movePercent,1f,0.9f));
//移动menuView
ViewHelper.setTranslationX(menuView,floatEvaluator.evaluate(movePercent,-menuView.getMeasuredWidth()/2,0));
//放大menuView
ViewHelper.setScaleX(menuView,floatEvaluator.evaluate(movePercent,0.5f,1f));
ViewHelper.setScaleY(menuView,floatEvaluator.evaluate(movePercent,0.5f,1f));
//改变menuView的透明度
ViewHelper.setAlpha(menuView,floatEvaluator.evaluate(movePercent,0.3f,1f));
}
public void smoothSlideViewTo(View view,int left,int top){
mViewHelper.smoothSlideViewTo(view, left, top);
refreshUI();
}
public void refreshUI(){
ViewCompat.postInvalidateOnAnimation(this);
}
@Override
public void computeScroll() {
if(mViewHelper.continueSettling(true)){
refreshUI();
}
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
menuView = getChildAt(0);
mainView = getChildAt(1);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
moveRange = (int) (getMeasuredWidth()*0.6);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mViewHelper.processTouchEvent(event);
return true;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mViewHelper.shouldInterceptTouchEvent(ev);
}
public interface onDragSlideMenuListener{
void close();
void open();
}
/**
* 判断slidemenu是否打开状态
* @return
*/
public boolean isOpen(){
boolean temp = false;
if(currentState==state.CLOSE){
temp = false;
}
if(currentState==state.OPEN){
temp = true;
}
return temp;
}
public state getCurrentState() {
return currentState;
}
}
</span>
布局文件如下:
<span style="font-size:18px;">activity_main</span>
<span style="font-size:18px;"><pre name="code" class="html"><com.slidmenu.view.SildMenuView
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"
android:background="@drawable/bg"
android:id="@+id/slidmenu"
>
<include layout="@layout/layout_menu"/>
<include layout="@layout/layout_main"/>
</com.slidmenu.view.SildMenuView>
</span>
左侧菜单layout_menu.xml
<span style="font-size:18px;"><pre name="code" class="html"><?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="300dp"
android:orientation="vertical"
android:paddingLeft="20dp"
android:paddingTop="50dp" >
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/head" />
<ListView
android:id="@+id/menu_listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="5dp"
android:listSelector="@android:color/transparent" >
</ListView>
</LinearLayout></span>
内容区布局:layout_main.xml
<span style="font-size:18px;"><pre name="code" class="html"><?xml version="1.0" encoding="utf-8"?>
<com.slidmenu.view.MainViewGroup xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/ll_main_root"
android:background="#ffffff"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#18B4ED" >
<ImageView
android:layout_width="30dp"
android:layout_marginLeft="15dp"
android:id="@+id/iv_head"
android:layout_height="30dp"
android:layout_centerVertical="true"
android:background="@drawable/head" />
</RelativeLayout>
<ListView android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/main_listview"
android:cacheColorHint="#00000000"
android:dividerHeight="0.8dp"
android:divider="#e5e5e5"
android:listSelector="@android:color/transparent"></ListView>
</com.slidmenu.view.MainViewGroup></span>
使用到的第三方jar:
<span style="font-size:18px;">nineoldandroids-2.4.0.jar
</span>
<span style="font-size:18px;"></pre><pre code_snippet_id="1603295" snippet_file_name="blog_20160309_18_5725033" name="code" class="html"></span>