一 需求:实现view的点击缩放效果,类似于携程首页。

二 需求分析:对于单纯的view的缩放还是比较简单的,我们使用单纯的android缩放动画就可以实现。但是按照携程首页的view来做的话,里面是有很多细节是我们需要处理的。

1 对于一张图片,当我们按下然后左右滑动时它应该仍然处于缩放状态,直到我们的手指脱离开view的边界才回到初始状态。

2 如果说我们的view的父控件是scrollview的话,这里就需要用到android中事件分发的相关知识了。

当我们按下view时,需要view来处理接下来的事件,但如果我们是向上或者向下滑动的话,当滑出一小段距离时,我们需要把view重置为

初始状态,同时把事件交给scrollview来处理使其可以进行上下滑动。

三 说了这么多,相信大家还是有点摸不着头脑的,没关系,我们先来张屏幕截图,然后我们直接贴出源码。

运行效果:

缩放view源码:

package com.example.asiatravel.ctriphomescaleview.view;

import android.animation.AnimatorSet;

import android.animation.ObjectAnimator;

import android.content.Context;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.view.View;

import android.view.animation.LinearInterpolator;

import android.widget.ImageView;

/**

* Created by kuangxiaoguo on 16/8/30.

*/

public class CTripHomeScaleView extends ImageView {

/**

* 动画持续时长

*/

private static final int DURATION = 100;

/**

* 快速点击的时间间隔

*/

private static final int TIME_DELAY = 500;

/**

* 滑动最小距离

*/

private static final int MIN_MOVE_DPI = 10;

/**

* 缩放的scale

*/

private static final float SMALL_SCALE = 0.95f;

/**

* 初始scale

*/

private static final float ONE_SCALE = 1f;

/**

* 判断缩小动画有没有执行过

*/

private boolean hasDoneAnimation;

/**

* 点击事件监听

*/

private OnClickListener listener;

/**

* 开始动画

*/

private AnimatorSet beginAnimatorSet;

/**

* scale返回动画

*/

private AnimatorSet backAnimatorSet;

private int downX;

private int downY;

private long lastClickTime;

public CTripHomeScaleView(Context context) {

this(context, null);

}

public CTripHomeScaleView(Context context, AttributeSet attrs) {

this(context, attrs, 0);

}

public CTripHomeScaleView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

initAnimation();

}

/**

* Init scale animation

*/

private void initAnimation() {

ObjectAnimator beginXAnimation = ObjectAnimator.ofFloat(this, "scaleX", ONE_SCALE, SMALL_SCALE).setDuration(DURATION);

beginXAnimation.setInterpolator(new LinearInterpolator());

ObjectAnimator beginYAnimation = ObjectAnimator.ofFloat(this, "scaleY", ONE_SCALE, SMALL_SCALE).setDuration(DURATION);

beginYAnimation.setInterpolator(new LinearInterpolator());

ObjectAnimator backXAnimation = ObjectAnimator.ofFloat(this, "scaleX", SMALL_SCALE, ONE_SCALE).setDuration(DURATION);

backXAnimation.setInterpolator(new LinearInterpolator());

ObjectAnimator backYAnimation = ObjectAnimator.ofFloat(this, "scaleY", SMALL_SCALE, ONE_SCALE).setDuration(DURATION);

backYAnimation.setInterpolator(new LinearInterpolator());

beginAnimatorSet = new AnimatorSet();

beginAnimatorSet.play(beginXAnimation).with(beginYAnimation);

backAnimatorSet = new AnimatorSet();

backAnimatorSet.play(backXAnimation).with(backYAnimation);

}

@Override

public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

/**

* 判断是不是快速点击

*/

if (isFastClick()) {

return true;

}

/**

* 请求父类不要拦截我的事件,意思是让我来处理接下来的滑动或别的事件

*/

getParent().requestDisallowInterceptTouchEvent(true);

downX = (int) event.getX();

downY = (int) event.getY();

hasDoneAnimation = false;

post(new Runnable() {

@Override

public void run() {

beginAnimatorSet.start();

}

});

break;

case MotionEvent.ACTION_MOVE:

int moveX = (int) event.getX();

int moveY = (int) event.getY();

int moveDistanceX = Math.abs(moveX) - downX;

int moveDistanceY = Math.abs(moveY) - downY;

/**

* 这里是判断是向左还是向右滑动,然后用view的宽度计算出一个距离compareWidth,当滑动距离超出compareWidth时,需要执行返回动画.

*/

int compareWidth = moveDistanceX > 0 ? getWidth() - downX : downX;

/**

* 第一个条件:判断向上或向下滑动距离大于滑动最小距离

* 第二个条件:判断向左或向右的滑动距离是否超出(compareWidth-最小距离)

* 第三个条件:判断有没有执行过返回动画并在执行过一次后置为true.

*/

if ((Math.abs(moveDistanceY) > dip2px(MIN_MOVE_DPI) || Math.abs(moveDistanceX) >= compareWidth - dip2px(MIN_MOVE_DPI)) && !hasDoneAnimation) {

/**

* 一 只要满足上述条件,就代表用户不是点击view,而是执行了滑动操作,这个时候我们就需要父类以及我们的最上层的控件来

* 拦截我们的事件,让最外层控件处理接下来的事件,比如scrollview的滑动.

* 二 因为我们执行了滑动操作,所以要执行view的返回动画

*/

getParent().requestDisallowInterceptTouchEvent(false);

hasDoneAnimation = true;

post(new Runnable() {

@Override

public void run() {

backAnimatorSet.start();

}

});

}

break;

case MotionEvent.ACTION_UP:

/**

* 这里如果我们是单纯的点击事件就会执行

*/

if (!hasDoneAnimation) {

hasDoneAnimation = true;

post(new Runnable() {

@Override

public void run() {

backAnimatorSet.start();

}

});

post(new Runnable() {

@Override

public void run() {

/**

* 接口回调点击事件

*/

if (listener != null) {

listener.onClick(CTripHomeScaleView.this);

}

}

});

}

break;

}

return true;

}

public void setOnClickListener(OnClickListener l) {

listener = l;

}

public interface OnClickListener {

void onClick(View v);

}

/**

* Make dp to px

*

* @param dipValue dp you need to change

* @return Get px according to your dp value.

*/

public int dip2px(float dipValue) {

final float scale = getResources().getDisplayMetrics().density;

return (int) (dipValue * scale + 0.5f);

}

/**

* Judge is fast click event.

*

* @return Is fast click or not.

*/

public boolean isFastClick() {

long time = System.currentTimeMillis();

long timeD = time - lastClickTime;

if (timeD < TIME_DELAY) {

return true;

} else {

lastClickTime = time;

return false;

}

}

}

总结:代码量不多,主要的逻辑是在处理view的onTouch事件时,注释在代码里写的还算清晰,所以这里就不在做赘述了,不懂的童鞋可以在下面留言,或者可以发邮件:kuangxiaoguo@163.com。

Android携程高级用法,Android真正仿携程首页view实现相关推荐

  1. android工具am的用法,Android am/pm命令用法

    am命令的参数介绍: usage: am [subcommand] [options] start an Activity: am start [-D] -D: enable debugging se ...

  2. android五大布局的用法,android:stretchColumns用法

    TableLayout是一个使用复杂的布局,最简单的用法就仅仅是拖拉控件做出个界面,但实际上,会经常在代码里使用TableLayout,例如做出表格的效果.本文主要介绍TableLayout的基本使用 ...

  3. android工具am的用法,Android中AM、PM、dumpsys命令使用总结

    在平时开发中,通过命令行有时候能够快速的帮我们实现一些功能,这里对常用的命令做一些总结. 1.AM命令用法 1.1.简单介绍 am指令是 activity manager的缩写,可以启动Service ...

  4. android中tag的用法,Android中setTag的用法

    首先我们要知道setTag 是干什么的,官方给的api解释是: Tags Unlike IDs,tags are not used to identify views,Tags are essenti ...

  5. android 携程日历控件,仿携程酒店日历组件for小程序

    仿携程酒店日历 接受日历组件开发之前,本来是拒绝的,日历组件,表单组件绝逼是前端开发的一个噩梦,尤其要做好一个旅游项目的日历,产品的收货标准只有一条,你看携程都实现了哦, MMP的.要在小程序中实现携 ...

  6. android 携程页面,android 仿携程首页源码(自定义button)

    [实例简介] [实例截图] [核心代码] package com.example.xiechengdemo; import android.content.Context; import androi ...

  7. Android列表用法之二:实战ListView高级用法

    在我们的项目中,并不是所有列表都是简单的使用.类似于新闻列表.QQ聊天列表等,具有图文并排的列表,每个item都有它不同的布局类型,都有其不同的实现方式.这类复杂的列表表现形式,在各类知名应用当中,不 ...

  8. (转)Android属性动画完全解析(中),ValueAnimator和ObjectAnimator的高级用法

    版权声明:本文出自郭霖的博客,转载必须注明出处. 目录(?)[-] ValueAnimator的高级用法 ObjectAnimator的高级用法 转载请注明出处:http://blog.csdn.ne ...

  9. android 属性动画实例,Android属性动画完全解析 中 ,ValueAnimator和ObjectAnimator的高级用法...

    大家好,在上一篇文章当中,我们学习了Android属性动画的基本用法,当然也是最常用的一些用法,这些用法足以覆盖我们平时大多情况下的动画需求了.但是,正如上篇文章当中所说到的,属性动画对补间动画进行了 ...

最新文章

  1. MySQL is running but PID file is not found
  2. PHP聚微商货源网源码
  3. 2021年中国单硝酸异山梨酯市场趋势报告、技术动态创新及2027年市场预测
  4. 观看杨老师(杨旭)Asp.Net Core MVC入门教程记录
  5. 开关电源和LDO的区别
  6. ucore Lab 1 系统软件启动过程
  7. UBUNTU内核升级后,如何更新 kernel headers
  8. HDU 4415 Assassin’s Creed 苦逼的贪心
  9. 百练1724ROADS
  10. 滚动抽奖html怎么做的,抽奖.html
  11. Minkowski不等式
  12. 原来3DMAX入门应该这样学!
  13. 如何成为优秀的前端程序员?
  14. 大理石在哪【搜索排序】
  15. Python一些可能用的到的函数系列11 本地哈希和服务器哈希比对
  16. java单元测试自动生成测试用例插件diffblue cover和evosuite
  17. android迅雷包名,迅雷(com.xunlei.downloadprovider) - 7.21.1.7474 - 应用 - 酷安
  18. 基于HTML的SEO
  19. C#实现具有Aero效果的窗体
  20. 量化交易策略六_动量和反转策略

热门文章

  1. 小程序定制,挑战百日学习计划第31天(3D骰子制作)
  2. vmware虚拟安装ubuntu镜像下载
  3. 末日搜索神器3.0发布
  4. 新手须知,亚马逊listing怎么去优化?
  5. echarts折线图堆叠怎么设置_ECharts折线图堆叠设置为不堆叠的方法
  6. JAVA入门算法题(十三)
  7. JAVA 大数的乘法运算和取余运算
  8. 零付款就读,零风险就业,月薪过万不是传说
  9. leetcode系列-14. 最长公共前缀
  10. 金税盘wtautoreg.exe 无法定位程序输入点SKFC_CleanMemeory于动态链接库