View体系第二篇:View滑动
View滑动的基本思想:当点击事件传到View时,系统记下触摸点的坐标,手指移动时系统记下触摸后的坐标并计算出偏移量,然后根据偏移量修正View坐标.
实现View滑动共有6种方法:layout()方法,offsetTopAndBottom(),LayoutParams,动画,scrollTo与scrollBy,以及Scroller.
一.layout()
import ...;
public class CustomView extends View {
private int lastX;
private int lastY;
public CustomView(Context context) {
super(context);
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public CustomView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//获取手指按下时,触摸点位置
lastX = x;
lastY = y;
break;
case MotionEvent.ACTION_MOVE:
//获取移动后触摸点位置,计算偏移量
int offsetX = x - lastX;
int offsetY = y - lastY;
//修改View的left,top,right,bottom属性重新放置View
layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);
break;
}
return true;
}
}
然后在布局文件中引用就好了:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical"
> <com.example.scroll_test.CustomView
android:layout_width="80dp"
android:layout_height="80dp"
android:background="@color/colorAccent"
/> </LinearLayout>
二.offsetLeftandRight
这种方法与Layout()方法相似,只需将ACTION_MOVE修改成以下代码:
case MotionEvent.ACTION_MOVE:
int offsetX = x - lastX;
int offsetY = y - lastY;
offsetLeftAndRight(offsetX);
offsetTopAndBottom(offsetY);
break;
}
三.LayoutParams(改变布局参数)
通过LayoutParams改变View的布局参数,从而达到修改View位置的效果.
将ACTION_MOVE修改成以下代码:
case MotionEvent.ACTION_MOVE:
int offsetX = x - lastX;
int offsetY = y - lastY;
LinearLayout.LayoutParams layoutParams= (LinearLayout.LayoutParams) getLayoutParams();
layoutParams.leftMargin=getLeft() + offsetX;
layoutParams.topMargin=getTop() + offsetY;
setLayoutParams(layoutParams);
break;
}
由于父控件是LinearLayout,所以用到了LineatLayout.LayoutParams.如果是RelativeLayout,则要使用RelativeLayot.LayoutParams.还可以用ViewGroup.MarginLayoutParams来实现:
ViewGroup.MarginLayoutParams layoutParams= (LinearLayout.LayoutParams) getLayoutParams();
layoutParams.leftMargin=getLeft() + offsetX;
layoutParams.topMargin=getTop() + offsetY;
setLayoutParams(layoutParams);
四.属性动画
ObjectAnimator.ofFloat(mCustomView,"translationX",0,300).setDuration().start();
五.scrollTo与scrollBy
scrollTo(x,y)表示移动到一个具体的点,scrollBy(dx,dy)表示移动的增量为dx,dy.
scrollTo,scrollBy移动的是View的内容,如果在ViewGround中使用,则是移动其所有的子View..我们将ACTION_MOVE替换成如下代码:
((View)getParent()).scrollBy(-offsetX,-offsetY);
设置为负值,则CustomView会跟随手滑动.原因是因为此时移动的是手机屏幕,布局是不移动的.布局中的控件也是不懂的,手指向右滑动后,想要View也向右滑动,则要把手机屏幕向着左边滑动,则布局相对向右滑动,实现跟手的效果.
六.Scroller
这个方法的实现效果比较类似动画,不过与动画相比其只可以用来实现滑动效果.
首先要初始化这个scroller:
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
scroller=new Scroller(context);
}
接下来重写computeScroll()方法,该方法会在View绘制时的draw()中调用
@Override
public void computeScroll() {
super.computeScroll();
if(scroller.computeScrollOffset()){
((View)getParent()).scrollTo(scroller.getCurrX(),scroller.getCurrY());
//通过不断调用invalidate(),不断返回调用computeScroll,更新View位置
// 直到scroller.computeScrolloffset返回fasle(即dutation结束)
invalidate();
}
}
同时在CustomView中写一个方法:
public void smoothScrollTo(int destX,int dextY){
int scrollX=getScrollX();
int deltaX=destX-scrollX;
//startScroll (int startX, int startY, int dx, int dy, int duration)
scroller.startScroll(scrollX,0,deltaX,0,2000);
invalidate();
}
通过在代码中调用自定义控件的smoothScrollTo方法,可以实现View的滑动效果.
View体系第二篇:View滑动的更多相关文章
- Android学习笔记(第二篇)View中的五大布局
PS:人不要低估自己的实力,但是也不能高估自己的能力.凡事谦为本... 学习内容: 1.用户界面View中的五大布局... i.首先介绍一下view的概念 view是什么呢?我们已经知道一个Act ...
- View体系第一篇:基础
View体系的学习内容为学习刘望舒先生博客总结的内容,大家可到他的博客看到更详细的内容. 一.view之间的继承关系 Viewground用来包裹其他view.在平常的使用中,我们不会直接用到View ...
- 《Android进阶之光》--View体系与自定义View
No1: View的滑动 1)layout()方法的 public class CustomView extends View{ private int lastX; private int last ...
- Android View体系(一)视图坐标系
前言 Android View体系是界面编程的核心,他的重要性不亚于Android四大组件,在这个系列中我会陆续讲到View坐标系.View的滑动.View的事件分发等文章来逐步介绍Android V ...
- Android View体系(四)从源码解析Scroller
在Android View体系(二)实现View滑动的六种方法这篇文章中我们讲到了用Scroller来实现View的滑动,所以这篇文章我们就不介绍Scroller是如何使用的了,本篇就从源码来分析下S ...
- android自定义View之仿通讯录侧边栏滑动,实现A-Z字母检索
我们的手机通讯录一般都有这样的效果,如下图: OK,这种效果大家都见得多了,基本上所有的android手机通讯录都有这样的效果.那我们今天就来看看这个效果该怎么实现. 一.概述 1.页面功能分析 整体 ...
- Android View体系(三)属性动画
上一篇文章讲了View滑动的六种方法,其中一种是使用动画,这篇文章我们来讲一讲动画的其中一种:属性动画. 1.android视图动画和属性动画 视图动画我们都了解,它提供了AlphaAnimation ...
- Android View体系(八)从源代码解析View的layout和draw流程
相关文章 Android View体系(一)视图坐标系 Android View体系(二)实现View滑动的六种方法 Android View体系(三)属性动画 Android View体系(四)从源 ...
- Android View体系(十)自定义组合控件
相关文章 Android View体系(一)视图坐标系 Android View体系(二)实现View滑动的六种方法 Android View体系(三)属性动画 Android View体系(四)从源 ...
随机推荐
- 使用Keras搭建cnn+rnn, BRNN,DRNN等模型
Keras api 提前知道: BatchNormalization, 用来加快每次迭代中的训练速度 Normalize the activations of the previous layer a ...
- [原创]K8Cscan插件之Mysql密码爆破
[原创]K8 Cscan 大型内网渗透自定义扫描器 https://www.cnblogs.com/k8gege/p/10519321.html Cscan简介:何为自定义扫描器?其实也是插件化,但C ...
- (转)EVMON_FORMAT_UE_TO_TABLES procedure - move an XML document to relational tables
原文:https://www.ibm.com/support/knowledgecenter/zh/SSEPGG_9.8.0/com.ibm.db2.luw.sql.rtn.doc/doc/r0054 ...
- mysql 开发进阶篇系列 48 物理备份与恢复(xtrabackup 的增量备份与恢复,以及备份总结)
一.增量备份概述 xtrabackup 和innobackupex 二个工具都支持增量备份,这意味着能复制自上次备份以来更改的数据.可以在每个完整备份之间执行许多增量备份,因此,您可以设置一个备份 ...
- 解决java.lang.IllegalArgumentException: No converter found for return value of type: class java.util.ArrayList的问题
一.背景 最近闲来无事,想自己搭建一套Spring+SpringMVC+Mybatis+Mysql的环境(搭建步骤会在以后博客中给出),结果运行程序时,适用@ResponseBody注解进行返回Lis ...
- Android数据保存之SharedPreference
前言: 程序中处理的大部分问题都与数据有关,读取数据显示在UI上,读取的数据可以是本地的,也可以是网络的.保存用户数据到存储空间,可以是本地的数据库,文件等,也可以是保存到网络服务器.总之大部分的程序 ...
- 在vue中使用Autoprefixed
为了使我们的项目兼容各种浏览器,我们可能会在开发中写大量的前缀.即使有了IDE为我们提供了便捷的方式.但是仍然需要我们去花时间和精力.而这样会浪费我们很多的时间.为了在开发中提升团队的开发效率,并且同 ...
- java for循环里面执行sql语句操作,有效结果只有一次,只执行了一次sql mybatis 循环执行update生效一次 实际只执行一次
java后台controller中,for循环执行数据库操作,但是发现实际仅仅执行了一次,或者说提交成功了一次,并没有实际的个数循环 有可能是同一个对象导致的 可以仔细看一下下面两段代码有什么区别 p ...
- 网络基础知识 - HTTP协议
前传:HTTP协议的演变过程 HTTP(HyperText Transfer Protocol)协议是基于TCP的应用层协议,它不关心数据传输的细节,主要是用来规定客户端和服务端的数据传输格式,最初是 ...
- python重试库retryiny源码剖析
上篇博文介绍了常见需要进行请求重试的场景,本篇博文试着剖析有名的python第三方库retrying源码. 在剖析其源码之前,有必要讲一下retrying的用法,方便理解. 安装: pip insta ...