高仿手机QQ5.0界面框架

这次的手机QQ更新从客观的角度来说,还是很好的,更加简约,控件也自定义了,界面也有了大的改动,但是最主要的框架还是它的左右滑动机制。让我们先来看看它的效果。

可以看到它是从左到右的一个滑动方法菜单的方式,最主要的就是这个控件类的实现吧。其他的感觉都没什么太大的问题,下面我就来看看这种效果应该怎么来实现。

第一拿到东西先分析这个效果是怎么出来的。我仔细的看了一下主要应该注意这几点。

1:菜单的出现有个放大效果而且伴随着一个apha的效果

2:主要的内容面板上面就是一个缩放的动画

3:可以看到这个菜单的边界和主内容面板上面的边界距离。我取的是1/4这里应该没错。

4:还应该注意的就是listview这些控件的事件屏蔽。

主要的问题应该就是这几个吧。

下面我就以怎么实现这个可滑动的pager来给大家说说代码实现。

package com.edsheng.view;

import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.Toast;

/**
 * @version 1.0
 * @FielName : DragPager.java
 * @Date : 2014/8/5
 * @author edsheng
 */
public class DragPager extends RelativeLayout {

	private View mMenu; // 菜单
	private View mContent; // 内容视图

	private int mStartx = 0; // 点击开始
	private float mContentStartTransX = 0; // 内容视图开始点击滑动的距离
	private float mMenuStartTransX = 0;// 菜单开始点击滑动的距离
	private int DEFAULT_RIGHT_MARGIN = getResources().getDisplayMetrics().widthPixels / 4;// 菜单距离边界距离在取的1/4屏幕

	ObjectAnimator mContent_animator;// 内容视图动画
	ObjectAnimator mMenu_animator;// 菜单动画
	private boolean misDrag = false; // 当前是否拖动
	final int DEFALT_DRAG_DISTENCE = 40;// 认为滑动的缺省值

	public DragPager(Context context) {
		super(context);
	}

	public DragPager(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	public DragPager(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public void setMenu(View menu) {
		mMenu = menu;
		LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT,
				LayoutParams.MATCH_PARENT);
		layoutParams.rightMargin = DEFAULT_RIGHT_MARGIN;
		addView(menu, layoutParams);
		mMenu.setScaleY(0.75f);// 初始化Y到0.75这么高
		mMenu.setTranslationX(-DEFAULT_RIGHT_MARGIN * 3);// 初始化菜单到-Y距离
	}

	public void setContent(View content) {
		mContent = content;
		addView(content);
	}

	/**
	 * 计算当前MenuX可滑动的位置
	 *
	 * @param distence
	 * @return
	 */
	private float getMenuDragX(float distence) {
		float newX = distence + mMenuStartTransX;
		if (newX <= -DEFAULT_RIGHT_MARGIN * 3) {
			newX = -DEFAULT_RIGHT_MARGIN * 3;
		} else if (newX >= 0) {
			newX = 0;
		}
		return newX;
	}

	/**
	 * 计算内容视图X滑动的位置
	 *
	 * @param distence
	 * @return
	 */
	private float getContentDragX(float distence) {

		float newX = distence + mContentStartTransX;
		if (newX <= 0) {
			newX = 0;
		} else if (newX >= mContent.getWidth() - DEFAULT_RIGHT_MARGIN) {
			newX = mContent.getWidth() - DEFAULT_RIGHT_MARGIN;
		}
		return newX;
	}

	/**
	 * 停止动画
	 */
	private void stopAnimation() {
		if (mContent_animator != null && mMenu_animator != null) {
			mContent_animator.cancel();
			mMenu_animator.cancel();
		}
	}

	// 移动
	private void move(float distence) {
		float nowx = getContentDragX(distence);
		if (nowx != mContent.getTranslationX()) {
			mContent.setTranslationX(nowx);
			float scale = nowx / (mContent.getWidth() - DEFAULT_RIGHT_MARGIN); // 计算alph范围是0-1
			mContent.setScaleY(1 - scale * 0.25f); // 内容的Y缩放
			mMenu.setTranslationX(getMenuDragX(distence)); // 设置菜单的距离
			mMenu.setScaleY(0.75f + scale * 0.25f);// 设置菜单的Y缩放
			mMenu.setAlpha(scale);// 菜单的Alpha
		}
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		switch (ev.getAction()) {
		case MotionEvent.ACTION_DOWN:
			stopAnimation(); // 停止动画
			mStartx = (int) ev.getRawX(); // 获取点击初始化x
			if (mContent != null)
				mContentStartTransX = mContent.getTranslationX();// 获取初始化x
			if (mMenu != null)
				mMenuStartTransX = mMenu.getTranslationX();
			break;
		case MotionEvent.ACTION_MOVE:
			// 当左右滑动到阀值就认为是在拖动了
			if (Math.abs(ev.getRawX() - mStartx) > DEFALT_DRAG_DISTENCE) {
				misDrag = true;
			}
			break;
		case MotionEvent.ACTION_UP:
			misDrag = false;
			break;
		}
		return super.dispatchTouchEvent(ev);
	}

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		if (misDrag) {
			return true;// 不进行向下分发了已经拦截
		} else {
			return false; // 把事件交给子view处理然后通过子view的dispatch分发
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (event.getActionIndex() > 1)
			return true;
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			return true; // 消费掉这个事件让它不传递
		case MotionEvent.ACTION_MOVE:
			float distence = event.getRawX() - mStartx; // 在这里处理移动
			move(distence);
			break;
		case MotionEvent.ACTION_UP:
		case MotionEvent.ACTION_CANCEL:
			toggle(); // 窗口回弹
			break;
		}
		return super.onTouchEvent(event);
	}

	/**
	 * 回弹的动画
	 */
	private void toggle() {
		if (mContent.getTranslationX() > DEFAULT_RIGHT_MARGIN * 2) {
			// 向右动画
			// 先是content动画
			PropertyValuesHolder content_transani = PropertyValuesHolder
					.ofFloat("translationX", mContent.getTranslationX(),
							mContent.getWidth() - DEFAULT_RIGHT_MARGIN);
			PropertyValuesHolder content_ScaleY = PropertyValuesHolder.ofFloat(
					"scaleY", mContent.getScaleY(), 0.75f);
			mContent_animator = ObjectAnimator.ofPropertyValuesHolder(mContent,
					content_transani, content_ScaleY);
			mContent_animator.start();

			// 这里菜单动画

			PropertyValuesHolder menu_transani = PropertyValuesHolder.ofFloat(
					"translationX", mMenu.getTranslationX(), 0);
			PropertyValuesHolder menu_ScaleY = PropertyValuesHolder.ofFloat(
					"scaleY", mMenu.getScaleY(), 1f);
			PropertyValuesHolder menu_Alpha = PropertyValuesHolder.ofFloat(
					"Alpha", mMenu.getAlpha(), 1f);
			mMenu_animator = ObjectAnimator.ofPropertyValuesHolder(mMenu,
					menu_transani, menu_ScaleY, menu_Alpha);
			mMenu_animator.start();

		} else {
			// 向左动画
			PropertyValuesHolder content_transanx = PropertyValuesHolder
					.ofFloat("translationX", mContent.getTranslationX(), 0);
			PropertyValuesHolder content_ScaleY = PropertyValuesHolder.ofFloat(
					"scaleY", mContent.getScaleY(), 1.0f);
			mContent_animator = ObjectAnimator.ofPropertyValuesHolder(mContent,
					content_transanx, content_ScaleY);
			mContent_animator.start();

			PropertyValuesHolder menu_transani = PropertyValuesHolder.ofFloat(
					"translationX", mMenu.getTranslationX(),
					-DEFAULT_RIGHT_MARGIN * 3);
			PropertyValuesHolder menu_ScaleY = PropertyValuesHolder.ofFloat(
					"scaleY", mMenu.getScaleY(), 0.75f);
			PropertyValuesHolder menu_Alpha = PropertyValuesHolder.ofFloat(
					"Alpha", mMenu.getAlpha(), 0f);
			mMenu_animator = ObjectAnimator.ofPropertyValuesHolder(mMenu,
					menu_transani, menu_ScaleY, menu_Alpha);
			mMenu_animator.start();
		}

	}

}

其中需要注意的地方就是事件的屏蔽和拖动的处理,然后就是几个缩放的地方,然后我们来验证一下这个控件是可用,它的左边是一个menu右边是一个content当我们需要使用的时候应该这样来使用。

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		DragPager dragPager = new DragPager(this);
		View content = new View(this);
		content.setBackgroundColor(Color.BLUE);
		dragPager.setContent(content);
		View mentu = new View(this);
		mentu.setBackgroundColor(Color.RED);
		dragPager.setBackgroundColor(Color.argb(122, 122, 122, 122));
		dragPager.setMenu(mentu);
		setContentView(dragPager);
}

最后还是来看看它的效果怎么样吧。

这里卡的原因主要是因为我的GIF做的不好的原因,然后只要这个界面出来了,其他的东西都比较好搞了,本来想彻彻底底的把手机QQ5.0的界面搬过来的,但是无耐手Q的加密现在做的越来越好了,拿不到资源了,不过这个界面都出来,我相信其他界面还是很容易搞定的吧,这个是里面我感觉最主要的一个东西。有兴趣的童鞋可以继续往下写哦,也可以把这个当成一个控件来用哦。

高仿手机QQ5.0界面框架

时间: 2024-08-09 01:09:18

高仿手机QQ5.0界面框架的相关文章

高仿网易4.0新UI框架

高仿网易4.0新UI框架 新的抽屉效果,修改于SliderViewController,首页滑动导航菜单随scrollView 的滑动变化效果. 下载地址:http://www.devstore.cn/code/info/500.html 运行截图:   热门源码下载: 高仿京东商城 Android快速开发不可或缺的11个工具类 Android快速开发框架LoonAndroid Android应用源码比较不错的新闻客户端 版权声明:本文为博主原创文章,未经博主允许不得转载.

【IOS源码】高仿网易4.0新UI框架

高仿网易4.0新UI框架 新的抽屉效果,修改于SliderViewController,首页滑动导航菜单随scrollView 的滑动变化效果. 下载地址: http://www.dwz.cn/yKQbV 效果图  

Android 高仿微信6.0主界面 带你玩转切换图标变色

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/41087219,本文出自:[张鸿洋的博客] 1.概述 学习Android少不了模仿各种app的界面,自从微信6.0问世以后,就觉得微信切换时那个变色的Tab图标屌屌的,今天我就带大家自定义控件,带你变色变得飞起~~ 好了,下面先看下效果图: 清晰度不太好,大家凑合看~~有木有觉得这个颜色弱爆了了的,,,下面我动动手指给你换个颜色: 有没有这个颜色比较妖一点~~~好了~下面开始介绍

jquery 仿手机屏幕切换界面效果

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

手机QQ5.0红点拖拽消除的实现

新版手机QQ5.+上新增了一种"一键退朝"的功能,即在页面上的红点可进行拖拽消除.在[知乎](http://www.zhihu.com/question/26382740)上可参考红点的设计过程.按照设计思路在Android上模仿手Q实现下拖拽的过程. 代码地址:https://github.com/chenupt/BezierDemo 效果图: 整体的思路,封装好一个view.在界面上找到四个点,即框出手势拖动点与红点之间的范围,利用贝塞尔曲线修饰边框,计算红点和手势拖动点间的距离,

高仿网易4.0新UI框架的Demo

NewsFourApp:一个模仿网易4.0新UI框架的开源项目. 声明:如果有好的修改,非常欢迎fork提交分享哈 —————————————-华丽丽的分割线——————————————— beta 0.2 —————————————-华丽丽的分割线——————————————— beta 0.1 1.新的抽屉效果,修改于SliderViewController,不过里面已经不一样,毕竟是新的效果嘛(此部分还不算完全具备框架的特性,呵呵??) 2.首页滑动导航菜单的字体大小和颜色,随scroll

实现仿微信6.0界面下-自定义view实现可变色的按钮

1.概述 学习Android少不了模仿各种app的界面,自从微信6.0问世以后,就觉得微信切换时那个变色的Tab图标屌屌的,今天我就带大家自定义控件,带你变色变得飞起~~ 好了,下面先看下效果图: 清晰度不太好,大家凑合看~~有木有觉得这个颜色弱爆了了的,,,下面我动动手指给你换个颜色: 有没有这个颜色比较妖一点~~~好了~下面开始介绍原理. 2.原理介绍 通过上面的效果图,大家可能也猜到了,我们的图标并非是两张图片,而是一张图,并且目标颜色是可定制的,谁让现在动不动就谈个性化呢. 那么我们如何

【Android】高仿QQ 5.0+ UI

每天接触的QQ客户端简介美观,特别是那个侧滑菜单更是吸引人,然后就想着自己做一个.前前后后折腾下来,总算有个样子了. 效果图 具体实现 登陆界面 主要是那个下拉列表,我是采用  PopUpWindow +ListView 实现 锁屏界面[Android]使用 SwipeRefreshLayout 实现下拉刷新 侧滑菜单使用 HorizontalScrollView +动画(使用了NineOldAndroids这个开源库) 主界面 底部菜单栏用RadioGroup实现,上面的内容页都是Fragme

高仿微信6.0底部切换标签设置Alpha渐变效果解析

本文参考:[张鸿洋的博客]http://blog.csdn.net/lmj623565791/article/details/41087219 先上关键的代码 <span style="color:#333333;">public class ChangeColorIconWithTextView extends View { private Bitmap mBitmap; private Canvas mCanvas; private Paint mPaint; /**