android 使用ViewDragHelper高仿QQ主界面效果

互联网有二家大公司做的产品是最好的,至少个人是这么认为的,一个是腾讯,一个是网易,今天就使用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>
 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值