OpenStack 开发架构设计的一些问题请教下各位。

基于 OpenStack 做私有云开发,前端自己重新做页面设计,预计只采用虚拟机管理和网络相关的一些功能,需要再做一个后端吗?不确定前端开发直接和 OpenStack api 通信是否合理。
OpenStack 开发 API 私有7 条回复 • 2021-06-30 11:32:39 +08:00
alexsunxl 1
alexsunxl 2 天前
肯定还是要做。 现在不做,后面需求变一点点,还得搞整改。
直接通信肯定会有很多问题的。
defunct9 2
defunct9 2 天前
openstack 太沉重了
buchikoma 3
buchikoma 2 天前
我们目前是前端对接 openapi,openapi 对接 openstack 的 Nova-api 这些
fengjianxinghun 4
fengjianxinghun 2 天前
1. 假如你是前端,那么肯定要做。
2. 假如你是后端,那么肯定不需要做。
3. 假如你是老板,*好别用 OpenStack 。。
HandForLove 5
HandForLove 2 天前
@fengjianxinghun 哈哈哈
HandForLove 6
HandForLove 2 天前
@buchikoma #抱拳,我去研究学习下。
quxuanxuan 7
quxuanxuan 1 天前
我们也在做私有云+混合云,开源的 https://github.com/yunionio/cloudpods, 可以参考下

[新功能] 腾讯轻量支持加入内网 CCN 连接 CVM 及 CDB

VPC 对等的功能期待很久了,Lightsail 其实很早就支持了,不过阿里那边迟迟没有跟进,产品迭代还是要看腾讯的了~

轻量本身是基于 CVM 的架构进行精简的,在互联方面没有给你配置 VPC 的选择,而是默认同地域置入一个账户下的 VPC 。既然本身是具有 VPC,那么在基础架构上也是一样支持 VPC 间互联的。这个功能在腾讯云被称为云联网,现在也支持绑定到轻量了~

注意配置 CCN 的时候不要跨地域!收费很贵的!

一、创建对应地域云联网

前往 CCN 页面,在对应地域新建一个 CCN,CCN 在同地域 5Gbps 下是没有任何费用的所以可以放心配置,选择将 CVM 、CDB 等所在的 VPC 接入进去: [url]https://console.cloud.tencent.com/vpc/ccn[/url]

二、建立轻量内网互联

在轻量的控制台中左侧已经上线了内网互联,选择对应的地域将其申请接入 CCN 。

三、接受轻量 VPC 连接申请

回到 CCN 的控制台,在页面中接受轻量 VPC 的接入许可,这时会自动生成两个 VPC 间的路由表,如果无冲突的话就可以完成互联了。

内网 0.2ms ,速度非常快,对于国内区域的机器间互联作用相当大~

四、修正 VPC 内网地址段

如果接入的 VPC 比较多,出现了和之前删除的 VPC 存在地址冲突,那么要去 VPC 设置中删掉无效的路由~

腾讯云本身系统生成的内网网段是不会冲突的,所以基本上不会遇到这个问题。

vpc ccn 内网 轻量10 条回复 • 2021-06-29 07:29:31 +08:00
ptstone 1
ptstone 2 天前
这个意思是 ,不同区域的主机 也可以免费组件一个局域网,然后还很快?
xxfye 2
xxfye 2 天前
轻量级就差这个了,有这个什么 IPv6,什么云 DB 都有了,还买 CVM 干嘛。
moult 3
moult 2 天前
@ptstone 跨地域收费。同地域 5G 带宽免费。
sekfung 4
sekfung 2 天前
感觉现在良心云无论是在产品功能和价格上,都要比套路用更具性价比了。良心云的四层 LB 都能支持 TCP +SSL 了,套路云还不肯支持。
keepeye 5
keepeye 2 天前
阿里云有 云企业网,类似的功能吧?我是用来不同帐号同地域服务器实现内网通信的
freecloud 6
freecloud 2 天前
/t/779044 nice 。配上无忧计划,香。
Rheinmetal 7
Rheinmetal 2 天前
@xxfye
要么是新一代产品试水要么是阉割了什么别的
stimw 8
stimw 2 天前 via Android
轻量就是没法换 ip,只能退了重买
Hanada 9
Hanada 2 天前 via Android
@keepeye 但是不支持轻量
dzyou2007 10
dzyou2007 2 天前 via Android
@xxfye 轻量支持 ipv6 了么

ubuntu关闭apt-get代理、设置http代理

今天想装个软件(wine),使用 sudo apt-get update 命令时,发现给出很多Ign 语句,总出现 Connecting to proxy.http://10.0.126.1:13128 的字样,发现这个代理是已经废弃掉的。接着想去取消使用该代理:

1、 查看/etc/apt/apt.conf,发现存在:

       http_proxy=”http://10.0.126.1:13128/”

       https_proxy=”https://10.0.126.1:13128/”

       ftp_proxy=”ftp://10.0.126.1:13128/”

       socks_proxy=”socks://10.0.126.1:13128/”

     直接删除该文件,重启电脑,发现问题还是没解决;

2、百度一下,命令行执行:export  http_proxy=”” 发现问题未解;

     执行 unset  http_proxy 问题还是存在;

3、查看~/.bashrc,未发现存在http_proxy之类设置;

4、env | grep proxy 发现依然存在 http 代理;

5、根目录查找一把: sudo grep -r -i http_proxy=http://10.0.126.168:13128/ ./

     看到控制台有输出: /etc/enviroment : http_proxy …..

6、查看一下:cat /etc/enviroment,发现有配置:

     http_proxy=”http://10.0.126.1:13128/”

     https_proxy=”https://10.0.126.1:13128/”

     tp_proxy=”ftp://10.0.126.1:13128/”

     socks_proxy=”socks://10.0.126.1:13128/”

7、vi /etc/enviroment 将配置删掉;

8、至此终于搞定然后  sudo apt-get UPDATE,出现n多更新。

记录一下。

ubuntu设置http代理:

方法一
    这是一种临时的手段,如果您仅仅是暂时需要通过http代理使用apt-get,您可以使用这种方式。
    在使用apt-get之前,在终端中输入以下命令(根据您的实际情况替换yourproxyaddressproxyport)。
export http_proxy=http://yourproxyaddress:proxyport

方法二
这种方法要用到/etc/apt/文件夹下的apt.conf文件。如果您希望apt-get(而不是其他应用程序)一直使用http代理,您可以使用这种方式。
注意: 某些情况下,系统安装过程中没有建立apt配置文件。下面的操作将视情况修改现有的配置文件或者新建配置文件。
sudo gedit /etc/apt/apt.conf
在您的apt.conf文件中加入下面这行(根据你的实际情况替换yourproxyaddressproxyport)。
Acquire::http::Proxy “http://yourproxyaddress:proxyport”;
保存apt.conf文件。

方法三
这种方法会在您的主目录下的.bashrc文件中添加两行。如果您希望apt-get和其他应用程序如wget等都使用http代理,您可以使用这种方式。
gedit ~/.bashrc
在您的.bashrc文件末尾添加如下内容(根据你的实际情况替换yourproxyaddressproxyport)。
http_proxy=http://yourproxyaddress:proxyport
export http_proxy
保存文件。关闭当前终端,然后打开另一个终端。
使用apt-get update或者任何您想用的网络工具测试代理。我使用firestarter查看活动的网络连接。
如果您为了纠正错误而再次修改了配置文件,记得关闭终端并重新打开,否自新的设置不会生效。或者通过source命令。

windows ccproxy下配置ubuntu代理

下载ccproxy,在设置中查看端口和自己本地ip(自动检测那里)

方法1:windows下载ccproxy,在设置中查看端口号,可以看到ip

%title插图%num

浏览器设置:linux 下输入firefox出现浏览器

右上角打开设置,选项,网络设置,preference->network setting

修改mannual proxy configuration,修改成自己的windows ip,完成浏览器可以上网

%title插图%num

 

方法二:

查看代理: env | grep proxy
配置代理:vi /etc/profile 末尾加上以下参数

local_ip=x.x.x.x(此处是widows下的ip,根据实际情况修改)
http_proxy=${local_ip}:808
https_proxy=${local_ip}:808
ftp_proxy=${local_ip}:808
socks_proxy=${local_ip}:808
export http_proxy https_proxy ftp_proxy

 

执行代理更新:.  /etc/profile(路径之前有空格)

使用ccproxy代理服务器上网

前段时间要在实验室搞一个hadoop集群出来,但是校园网当时不能用路由器,我自己只有一个校园网账号,要让三台电脑都上网。请教师兄,终于搞定了。

如果你之前使用iso文件作为源,参考文章http://blog.csdn.net/genius_zz/article/details/52563309

下载安装完成(自行百度),然后在设置里进行符合自己需要的设置
%title插图%num

然后保证同一个局域网下的需要上网的机器与可以上网的机器之间互相ping的通,然后,点击账号,填写需要联网的机器的ip地址。

%title插图%num

这里选择允许部分,然后新建即可。在代理机这边设置好了以后,转向需要上网的机器
(1) 编辑/etc/environment
添加如下:
http_proxy=”http://192.168.3.129:808/”
https_proxy=”https://192.168.3.129:808/”
ftp_proxy=”ftp://192.168.3.129:808/”
socks_proxy=”socks://192.168.3.129:808/”

(2)编辑/etc /apt/apt.conf
同样添加上述内容,然后source /etc/enrironment

(3) 验证设置是否生效
echo $http_proxy 输出如下结果表明设置正确:

然后ubuntu机器就可以上网了。

api代理ip是什么?怎么用?

如今许多互联网从业人员知道代理IP,也有不少人在使用代理IP,*常见的就是在网络爬虫方面的使用。

代理IP是代理IP服务器的简称,其本质是利用新IP地址代替自己的IP地址进行接入和操纵,就像网络信息中转站一样,具有很大的优势。

因特网已进入大数据时代,信息安全成为人们关注的焦点。如在上网时配合代理IP使用,使自己的IP成为动态IP,这样就可以将自己的IP隐藏起来,不必担心被追踪和攻击,提高了上网的安全性。

代理IP对于网络爬虫来说更为重要,因为现在很多网站都设置了反爬虫措施,但是当爬虫在短时间内发送过多请求时,会被封IP封掉,为了工作效率又必须快速爬取,如果爬虫配合代理IP来使用,就可以不断地切换IP,这样就可以让爬虫继续使用IP。

代理IP服务器可以提高网络的安全性,保证爬虫的工作效率,其重要性不言而喻,但只有高质量的代理IP才能达到理想的效果,例如智游代理,用户在选择代理IP时,要提前确定相关参数,才能取得理想的效果。

如何看待国内http代理ip的普及性

%title插图%num

目前看来,每个行业都或多或少地与网络有联系。那是一个网络连接的时代。实际上,每个人对网络的依赖性和使用性比以前更强了。

不管是隐藏自己的IP还是访问受限的网站,都无法避免要联系IP代理。由于只有通过IP代理工具,才能实现这些功能,但如果希望获得IP代理的功能服务,则应该首先对IP代理有一些了解。

代理服务器会将请求转发到目标服务器上,代理服务器会加密并压缩请求包,以保证信息的安全。

由于动态ip代理的流行,我们可以充分利用爬虫技术,大量收集数据。正如已经进行过爬行的人所知,抓取工具在抓取数据时确实需要大量的动态ip资源,并且可能每天要使用数百万的IP。

因此,代理服务的ip质量和数量是非常关键的,如果代理服务不具备良好的技术条件,那么所有可能提供的ip资源都会被重复使用,严重影响使用效果。

Android实现滑动的方法

下面通过一个例子来总结实现滑动的几种方式,例子的主要功能就是让我们的自定义View能够随着手指的移动而移动。
布局文件如下:
<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation=”vertical”
android:layout_width=”match_parent”
android:layout_height=”match_parent”>
<com.scu.lly.dragviewtest.view.DragView
android:layout_width=”100dp”
android:layout_height=”100dp” />
</LinearLayout>

方式一:layout方法
在View进行绘制时,会调用onLayout()方法来设置显示的位置,因此,我们可以通过修改View的left、top、right、bottom四个属性来控制View的坐标。要控制View随手指滑动,因此需要在onTouchEvent()事件中进行滑动控制。代码如下:
public class DragView extends View{

private int mLastX;
private int mLastY;

public DragView(Context context) {
super(context);
init();
}

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

public DragView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}

private void init(){
setBackgroundColor(Color.BLUE);
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
int x = (int) ev.getX();
int y = (int) ev.getY();
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
mLastX = x;
mLastY = y;
break;
case MotionEvent.ACTION_MOVE:
int offsetX = x – mLastX;
int offsetY = y – mLastY;
//调整layout的四个坐标
layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);
break;
}
return true;
}
}

方式二:offsetLeftAndRight()和offsetTopAndBottom()
这两个方法其实是对上面那种layout设置方式的封装、简化,在layout中,左left、右right两个方向都是加上offsetX,上top、下bottom两个方向都是加上offsetY,为了简化设置四个方向,Android提供了offsetLeftAndRight()来代替左右方向的设置,用offsetTopAndBottom()来代替上下方向的设置。
我们只需要修改上面代码ACTION_MOVE的部分,如下:
<span style=”white-space:pre”> </span>case MotionEvent.ACTION_MOVE:
int offsetX = x – mLastX;
int offsetY = y – mLastY;
//调整layout的四个坐标
//layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);
//使用简写形式
offsetLeftAndRight(offsetX);
offsetTopAndBottom(offsetY);
break;

方式三:LayoutParams
LayoutParams保存了一个View的布局参数,因此我们可以通过动态改变LayoutParams中的布局参数来达到改变View的位置效果。通过getLayoutParams()方法来获取View的LayoutParams,这里获取到的LayoutParams需要根据View所在父布局的类型来设置不同的类型,比如,我们这个自定义View是放在LinearLayout中的,那么通过getLayoutParams()获取到的就是LinearLayout.LayoutParams。因此,通过getLayoutParams()获取到LayoutParams的前提就是这个View需要有一个父布局。
同样,我们只需要修改上面代码ACTION_MOVE的部分,如下:
case MotionEvent.ACTION_MOVE:
int offsetX = x – mLastX;
int offsetY = y – mLastY;
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) getLayoutParams();
lp.leftMargin = getLeft() + offsetX;
lp.topMargin = getTop() + offsetY;
setLayoutParams(lp);
break;
可以看到,通过LayoutParams改变一个View的位置时,改变的是这个View的Margin属性,这也是为什么这种方式一定要有父布局的原因,只有有了父布局,margin属性的设置才会起作用。
对于使用LayoutParams这种方式改变View位置,如果我们不想考虑父布局的类型,还可以使用ViewGroup.MarginLayoutParams来进行设置,这样也更加方便。如下:
case MotionEvent.ACTION_MOVE:
int offsetX = x – mLastX;
int offsetY = y – mLastY;
//LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) getLayoutParams();
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) getLayoutParams();
lp.leftMargin = getLeft() + offsetX;
lp.topMargin = getTop() + offsetY;
setLayoutParams(lp);
break;
效果是一样的。

方式四:scrollTo与scrollBy
关于scrollTo()和scrollBy()方法,我这篇文章《Android Scroller大揭秘》中有详细介绍。

使用scrollTo()和scrollBy()方法需要注意的一点是,scrollTo()和scrollBy()方法移动的是View的content,即让View的内容移动,如果在ViewGroup中使用scrollTo()和scrollBy()方法,那么移动的将是所有的子View,如果在View中使用,那么移动的将是View的内容。例如,TextView,content就是它的文本,ImageView,content就是它的drawable对象。

因此,上面例子中我们如果直接这样使用:
scrollBy(offsetX,offsetY);
发现View并没有移动,但其实是发生了移动的,只不过此时移动的是View中的内容,而我们例子中的content什么也没有。
所以,我们要想使这个View发生移动,我们就应该在View所在的ViewGroup中使用scrollBy或scrollTo方法来进行移动。同时,使用者两个方法进行移动的时候,注意此时的坐标方向与平常是相反的,具体在《Android Scroller大揭秘》有讲解。代码如下:
case MotionEvent.ACTION_MOVE:
//int offsetX = x – mLastX;
//int offsetY = y – mLastY;
//此时,计算坐标是相反的
int offsetX = mLastX – x;
int offsetY = mLastY – y;
//让View所在的ViewGroup进行移动
((View)getParent()).scrollBy(offsetX,offsetY);
break;

方式五:Scroller
通过Scroller这个辅助类,配合scrollTo和scrollBy可以实现一些更加高级的滑动效果,关于Scroller类的具体介绍,同样在这篇文章中有详解《Android Scroller大揭秘》。

这里,我们只是结合上面这个例子实现一个简单的功能,当我们滑动完毕抬起手指后,View自动回弹到原来的位置。代码如下:
public class DragView extends View{

private int mLastX;
private int mLastY;
private Scroller mScroller;

public DragView(Context context) {
super(context);
init(context);
}

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

public DragView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}

private void init(Context context){
setBackgroundColor(Color.BLUE);
mScroller = new Scroller(context);
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
int x = (int) ev.getX();
int y = (int) ev.getY();
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
mLastX = x;
mLastY = y;
break;
case MotionEvent.ACTION_MOVE:
//int offsetX = x – mLastX;
//int offsetY = y – mLastY;
//此时,计算坐标是相反的
int offsetX = mLastX – x;
int offsetY = mLastY – y;
//让View所在的ViewGroup进行移动
((View)getParent()).scrollBy(offsetX,offsetY);
break;
case MotionEvent.ACTION_UP:
View viewGroup = (View) getParent();
mScroller.startScroll(viewGroup.getScrollX(),viewGroup.getScrollY(),-viewGroup.getScrollX(),-viewGroup.getScrollY());
//记住需要invalidate
invalidate();
break;
}
return true;
}

@Override
public void computeScroll() {
super.computeScroll();
if(mScroller.computeScrollOffset()){
((View)getParent()).scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
//记住,需要不断调用invalidate进行重绘
invalidate();
}
}
}

以上五种方法就是常用的滑动View的方法。还有两种方式能够控制一个View的移动效果:属性动画和使用ViewDragHelper,对于这两种方法,大家可以查阅网上资料,就不详细介绍了。

(以上内容来源于看《Android群英传》的总结)
————————————————

Android实现滑动的几种方式

View的滑动对于View交互性及效果有很大影响,我们可以通过以下四种方式来实现View的滑动,准确地说是View位置的改变。要改变View的位置,首先我们需要了解Android的坐标系,因为View的是通过坐标来定位的。

*对坐标系

Android系统中,屏幕的*左上角为坐标原点,如下图所示。

%title插图%num

屏幕*左上角的点为坐标原点,向右向下分别为x轴和y轴

视图坐标系

视图坐标系是在View的层级体系中使用到的,View的父布局*左上角为坐标原点,向右向下为x轴和y轴,如下图所示:

%title插图%num

几个容易混淆的方法:

getX():视图坐标系点的X坐标
getRawX():*对坐标系点的X坐标
getLeft():视图坐标系View左边框距离ViewGroup左边框距离
getTranslationX():View的偏移量,初始为0,当View发生平移时,其值会变,向右为正,向左为负。
其中view.getX() = view.getLeft() + view.getTranslationX(),而get*Y同理。

1. 通过改变View的布局位置

View的layout方法用来将View放到布局的合适位置,我们可以通过这个方法改变它的left,top,right,bottom参数的值来改变它在布局中的位置。在此基础上,如果我们在用户手指移动的过程中不断地改变View的位置就可以让View跟随手指移动。要实现View跟随用户手指滑动,我们可以监听用户手指的动作(按下,移动,。。。)计算偏移量,通过layout改变View的位置即可。

如下代码则通过layout实现View跟随手指滑动(重写View的onTouchEvent方法)

private int lastX;
private int lastY;

@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
Log.d(TAG,”onTouchEvent() down”);
lastX = x;
lastY = y;
break;
case MotionEvent.ACTION_MOVE:
Log.d(TAG,”onTouchEvent() move”);
int offX = x – lastX;
int offY = y -lastY;
layout(getLeft()+offX,getTop()+offY,getRight()+offX,getBottom()+offY);
break;
}
return true;
}

这里通过相对坐标计算偏移量完成View的滑动,还可以通过*对坐标计算偏移量,代码如下:

private int lastRawX;
private int lastRawY;

@Override
public boolean onTouchEvent(MotionEvent event) {
int rawX = (int) event.getRawX();
int rawY = (int) event.getRawY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
Log.d(TAG,”onTouchEvent() down”);
lastRawX = rawX;
lastRawY = rawY;
break;
case MotionEvent.ACTION_MOVE:
Log.d(TAG,”onTouchEvent() move”);
int offX = rawX – lastRawX;
int offY = rawY -lastRawY;
layout(getLeft()+offX,getTop()+offY,getRight()+offX,getBottom()+offY);
lastRawX = rawX; // 重置坐标
lastRawY = rawY; // 重置坐标
break;
}
return true;
}

与相对坐标不同的是,使用*对坐标需要在move事件结束后重置上一次手指的坐标值,这样才能准确地计算出偏移量。

为什么*对坐标要重置?那是如果不重置的话每次移动都是拿新的坐标与*开始的坐标比较得到偏移量,而*开始的坐标是View的初始位置手指按下的坐标,View每次移动的偏移量应该是新位置的坐标减去上一次的坐标,所以每次移动后需要更新上一次的坐标。

除了使用View的layout方法重新布局View外,还可以使用offsetLeftAndRight和offsetTopAndBottom方法重新布局View,同样可以实现View的滑动效果。代码如下:

private int lastRawX;
private int lastRawY;

@Override
public boolean onTouchEvent(MotionEvent event) {
int rawX = (int) event.getRawX();
int rawY = (int) event.getRawY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
Log.d(TAG,”onTouchEvent() down”);
lastRawX = rawX;
lastRawY = rawY;
break;
case MotionEvent.ACTION_MOVE:
Log.d(TAG,”onTouchEvent() move”);
int offX = rawX – lastRawX;
int offY = rawY -lastRawY;
offsetLeftAndRight(offX);
offsetTopAndBottom(offY);
// layout(getLeft()+offX,getTop()+offY,getRight()+offX,getBottom()+offY);
lastRawX = rawX;
lastRawY = rawY;
break;
}
return true;
}

还可以通过View的改变布局参数LayoutParams的leftMargin和topMargin属性值改变View的位置,实现View的滑动,代码如下:

private int lastRawX;
private int lastRawY;

@Override
public boolean onTouchEvent(MotionEvent event) {
int rawX = (int) event.getRawX();
int rawY = (int) event.getRawY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
Log.d(TAG,”onTouchEvent() down”);
lastRawX = rawX;
lastRawY = rawY;
break;
case MotionEvent.ACTION_MOVE:
Log.d(TAG,”onTouchEvent() move”);
int offX = rawX – lastRawX;
int offY = rawY -lastRawY;
// offsetLeftAndRight(offX);
// offsetTopAndBottom(offY);
// layout(getLeft()+offX,getTop()+offY,getRight()+offX,getBottom()+offY);
ViewGroup.LayoutParams layoutParams = getLayoutParams();
((ViewGroup.MarginLayoutParams)layoutParams).leftMargin += offX;
((ViewGroup.MarginLayoutParams)layoutParams).topMargin += offY;
setLayoutParams(layoutParams);
lastRawX = rawX;
lastRawY = rawY;
break;
}
return true;
}

改变View的布局参数需要注意的是这个View(或ViewGroup)必须有一个父布局,同时还需要注意布局参数的类型(如LinearLayout.LayoutParams,FrameLayout.LayoutParams),不过可以使用万能的MarginLayoutParams,这样就可以不用考虑布局参数类型了。

2. 使用scrollTo和scrollBy

View类有scrollTo和scollBy方法,它们可以改变View内容的位置,scrollTo表示移动到某个坐标点,scrollBy表示移动多少偏移量。我们可以通过scrollBy实现View跟随手指的滑动,代码如下:

private int lastRawX;
private int lastRawY;

@Override
public boolean onTouchEvent(MotionEvent event) {
int rawX = (int) event.getRawX();
int rawY = (int) event.getRawY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
Log.d(TAG,”onTouchEvent() down”);
lastRawX = rawX;
lastRawY = rawY;
break;
case MotionEvent.ACTION_MOVE:
Log.d(TAG,”onTouchEvent() move”);
int offX = rawX – lastRawX;
int offY = rawY -lastRawY;
// offsetLeftAndRight(offX);
// offsetTopAndBottom(offY);
// layout(getLeft()+offX,getTop()+offY,getRight()+offX,getBottom()+offY);
// ViewGroup.LayoutParams layoutParams = getLayoutParams();
// ((ViewGroup.MarginLayoutParams)layoutParams).leftMargin += offX;
// ((ViewGroup.MarginLayoutParams)layoutParams).topMargin += offY;
// setLayoutParams(layoutParams);
((View)getParent()).scrollBy(-offX,-offY);
lastRawX = rawX;
lastRawY = rawY;
break;
}
return true;
}

这里你可能会有所迷惑,为什么调用scrollBy的是View的父View(ViewGroup)?为什么偏移量是负的?

首先scrollBy移动的是View的内容content,而不是View本身,如TextView的content为文本,ImageView的content为drawable,而ViewGroup的content是View或是ViewGroup,所以要移动当前View本身,我们就需要通过它的ViewGroup改变自己的内容从而改变View本身的位置。其次,我们真正操作的是View的父控件ViewGroup,要让View往左(上/右/下)移,应该要让ViewGroup往相反方向移动,也就是右(下/左/上),所以偏移量就是相反的(负的)。下面贴上一张图,感受一下。

%title插图%num

3. 使用Scroller类实现View平滑移动

Android为View的滑动提供了Scroller辅助类,它本身并不能导致View滑动,需要借助computeScroll和ScrollTo方法完成View的滑动。使用Scroller类完成View的平滑,需要通过以下三个步骤:

(1)创建Scroller类

通常在自定义View的构造方法中完成Scroller类的初始化

mScroller = new Scroller(context);
1
(2)重写computeScroll方法

@Override
public void computeScroll() {
super.computeScroll();
// 判断Scroller滑动是否执行完毕
if(mScroller.computeScrollOffset()){
((View)getParent()).scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
// 通过重绘让系统调用onDraw,onDraw中又会调用computeScroll,如此不断循环,直到Scroller执行完毕
invalidate();
}
}

这里需要注意的是computeScroll方法在onDraw中会被调用,因此需要调用invalidate方法通知View调用onDraw重绘,然后再调用computeScroll完成View的滑动,过程为invalidate->onDraw->computeScroll->invalidate->…,无限循环直到mScroller的computeScrollOffset返回false,也就是滑动完成。

(3)调用Scroller类的startScroll方法开启滚动过程

public void smoothScrollBy(int dx,int dy){
mScroller.startScroll(mScroller.getFinalX(),mScroller.getFinalY(),dx,dy,2000);
invalidate(); // 必须调用改方法通知View重绘以便computeScroll方法被调用。
}

接下来就开始模拟滑动过程了,重写onTouchEvent方法,代码如下:

@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_UP:
int offX = x – lastX;
int offY = y -lastY;
smoothScrollBy(-offX,-offY);
break;
}
return true;
}

计算偏移量的方法和上面一样,这里实现的效果是手指离开时,View会在2秒内平滑到手指离开时的位置。

4. 使用属性动画实现View的滑动

属性动画可以改变View的属性,那么我们可以通过属性动画改变View的x和y属性从而改变View的位置实现View的滑动,代码如下:

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void animationScroll(float dx, float dy){
Path path = new Path();
path.moveTo(dx,dy);
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(this, “x”, “y”, path);
objectAnimator.start();
}

通过执行ObjectAnimator改变x和y属性,我们需要新的x和y属性值,可以通过重写onTouchEvent方法得到新的x和y属性值,代码如下:

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@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_UP:
int offX = x – lastX;
int offY = y -lastY;
animationScroll(getX()+offX,getY()+offY);
break;
}
return true;
}
————————————————

Android进阶之_实现滑动的7种方式详解

在android开发中,滑动对一个app来说,是非常重要的,流畅的滑动操作,能够给用户带来用好的体验,那么本次就来讲讲android中实现滑动有哪些方式。其实滑动一个View,本质上是移动一个View,改变其当前所属的位置,要实现View的滑动,就必须监听用户触摸的事件,且获取事件传入的坐标值,从而动画的改变位置而实现滑动。

android坐标系
首先要知道android的坐标系与我们平常学习的坐标系是不一样的,在android中是将左上方作为坐标原点,向右为x抽正方向,向下为y抽正方向,像在触摸事件中,getRawX(),getRawY()获取到的就是Android坐标中的坐标.

视图坐标系
android开发中除了上面的这种坐标以外,还有一种坐标,叫视图坐标系,他的原点不在是屏幕左上方,而是以父布局坐上角为坐标原点,像在触摸事件中,getX(),getY()获取到的就是视图坐标中的坐标.

触摸事件–MotionEvent
触摸事件MotionEvent在用户交互中,有非常重要的作用,因此必须要掌握他,我们先来看看Motievent中封装的一些常用的触摸事件常亮:

//单点触摸按下动作
public static final int ACTION_DOWN = 0;
//单点触摸离开动作
public static final int ACTION_UP = 1;
//触摸点移动动作
public static final int ACTION_MOVE = 2;
//触摸动作取消
public static final int ACTION_CANCEL = 3;
//触摸动作超出边界
public static final int ACTION_OUTSIDE = 4;
//多点触摸按下动作
public static final int ACTION_POINTER_DOWN = 5;
//多点触摸离开动作
public static final int ACTION_POINTER_UP = 6;

以上是比较常用的一些触摸事件,通常情况下,我们会在OnTouchEvent(MotionEvent event)方法中通过event.getAction()方法来获取触摸事件的类型,其代码模式如下:

@Override
public boolean onTouchEvent(MotionEvent event)
{
//获取当前输入点的坐标,(视图坐标)
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//处理输入按下事件
break;
case MotionEvent.ACTION_MOVE:
//处理输入的移动事件
break;
case MotionEvent.ACTION_UP:
//处理输入的离开事件
break;
}
return true; //注意,这里必须返回true,否则只能响应按下事件
}

以上只是一个空壳的架构,遇到的具体的场景,也有可能会新增多其他事件,或是用不到这么多事件等等,要根据实际情况来处理。在介绍如何实现滑动之前先来看看android中给我们提供了那些常用的获取坐标值,相对距离等的方法,主要是有以下两个类别:

View 提供的获取坐标方法

getTop(): 获取到的是View自身的顶边到其父布局顶边的距离

getBottom(): 获取到的是View自身的底边到其父布局顶边的距离

getLeft(): 获取到的是View自身的左边到其父布局左边的距离

getRight(): 获取到的是View自身的右边到其父布局左边的距离

MotionEvent提供的方法

getX(): 获取点击事件距离控件左边的距离,即视图坐标

getY(): 获取点击事件距离控件顶边的距离,即视图坐标

getRawX(): 获取点击事件距离整个屏幕左边的距离,即*对坐标

getRawY(): 获取点击事件距离整个屏幕顶边的距离,即*对坐标

介绍上面一些基本的知识点后,下面我们就来进入正题了,android中实现滑动的其中方法:

实现滑动的7种方法
其实不管是哪种滑动,他们的基本思路是不变的,都是:当触摸View时,系统记下当前的触摸坐标;当手指移动时,系统记下移动后的触摸点坐标,从而获得相对前一个点的偏移量,通过偏移量来修改View的坐标,并不断的更新,重复此动作,即可实现滑动的过程。
首先我们先来定义一个View,并置于LinearLayout中,我们的目的是要实现View随着我们手指的滑动而滑动,布局代码如下:

<?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=”match_parent”
android:orientation=”vertical”>

<com.liaojh.scrolldemo.DragView
android:layout_width=”100dp”
android:layout_height=”100dp”
android:background=”#88ffffff”/>

</LinearLayout>

layout方法
我们知道,在进行View绘制时,会调用layout()方法来设置View的显示位置,而layout方法是通过left,top,right,bottom这四个参数来确定View的位置的,所以我们可以通过修改这四个参数的值,从而修改View的位置。首先我们在onTouchEvent方法中获取触摸点的坐标:

float x = event.getX();
float y = event.getY();

接着在ACTION_DOWN的时候记下触摸点的坐标值:

case MotionEvent.ACTION_DOWN:
//记录按下触摸点的位置
mLastX = x;
mLastY = y;
break;

*后在ACTION_MOVE的时候计算出偏移量,且将偏移量作用到layout方法中:

case MotionEvent.ACTION_MOVE:
//计算偏移量(此次坐标值-上次触摸点坐标值)
int offSetX = (int) (x – mLastX);
int offSetY = (int) (y – mLastY);

//在当前left,right,top.bottom的基础上加上偏移量
layout(getLeft() + offSetX,
getTop() + offSetY,
getRight() + offSetX,
getBottom() + offSetY
);
break;

这样每次在手指移动的时候,都会调用layout方法重新更新布局,从而达到移动的效果,完整代码如下:

package com.liaojh.scrolldemo;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

/**
* @author LiaoJH
* @DATE 15/11/7
* @VERSION 1.0
* @DESC TODO
*/
public class DragView extends View
{
private float mLastX;
private float mLastY;

public DragView(Context context)
{
this(context, null);
}

public DragView(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}

public DragView(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
}

@Override
public boolean onTouchEvent(MotionEvent event)
{
//获取当前输入点的坐标,(视图坐标)
float x = event.getX();
float y = event.getY();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
//记录按下触摸点的位置
mLastX = x;
mLastY = y;
break;
case MotionEvent.ACTION_MOVE:
//计算偏移量(此次坐标值-上次触摸点坐标值)
int offSetX = (int) (x – mLastX);
int offSetY = (int) (y – mLastY);

//在当前left,right,top.bottom的基础上加上偏移量
layout(getLeft() + offSetX,
getTop() + offSetY,
getRight() + offSetX,
getBottom() + offSetY
);

break;
}
return true;
}
}

当然也可以使用getRawX(),getRawY()来获取*对坐标,然后使用*对坐标来更新View的位置,但要注意,在每次执行完ACTION_MOVE的逻辑之后,一定要重新设置初始坐标,这样才能准确获取偏移量,否则每次的偏移量都会加上View的父控件到屏幕顶边的距离,从而不是真正的偏移量了。

@Override
public boolean onTouchEvent(MotionEvent event)
{
//获取当前输入点的坐标,(*对坐标)
float rawX = event.getRawX();
float rawY = event.getRawY();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
//记录按下触摸点的位置
mLastX = rawX;
mLastY = rawY;
break;
case MotionEvent.ACTION_MOVE:
//计算偏移量(此次坐标值-上次触摸点坐标值)
int offSetX = (int) (rawX – mLastX);
int offSetY = (int) (rawY – mLastY);

//在当前left,right,top.bottom的基础上加上偏移量
layout(getLeft() + offSetX,
getTop() + offSetY,
getRight() + offSetX,
getBottom() + offSetY
);

//重新设置初始位置的值
mLastX = rawX;
mLastY = rawY;
break;
}
return true;
}

offsetLeftAndRight()与offsetTopAndBottom()
这个方法相当于系统提供了一个对左右,上下移动的API的封装,在计算出偏移量之后,只需使用如下代码设置即可:

offsetLeftAndRight(offSetX);
offsetTopAndBottom(offSetY);

偏移量的计算与上面一致,只是换了layout方法而已。

LayoutParams
LayoutParams保存了一个View的布局参数,因此可以在程序中通过动态的改变布局的位置参数,也可以达到滑动的效果,代码如下:

LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) getLayoutParams();
lp.leftMargin = getLeft() + offSetX;
lp.topMargin = getTop() + offSetY;
setLayoutParams(lp);

使用此方式时需要特别注意:通过getLayoutParams()获取LayoutParams时,需要根据View所在的父布局的类型来设置不同的类型,比如这里,View所在的父布局是LinearLayout,所以可以强转成LinearLayout.LayoutParams。

在通过改变LayoutParams来改变View的位置时,通常改变的是这个View的Margin属性,其实除了LayoutParams之外,我们有时候还可以使用ViewGroup.MarginLayoutParams来改变View的位置,代码如下:

ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) getLayoutParams();
lp.leftMargin = getLeft() + offSetX;
lp.topMargin = getTop() + offSetY;
setLayoutParams(lp);
//使用这种方式的好处就是不用考虑父布局类型

scrollTo与scrollBy
在一个View中,系统提供了scrollTo与scrollBy两种方式来改变一个View的位置,其中scrollTo(x,y)表示移动到一个具体的坐标点(x,y),而scrollBy(x,y)表示移动的增量。与前面几种计算偏移量相同,使用scrollBy来移动View,代码如下:

scrollBy(offSetX,offSetY);

然后我们拖动View,发现View并没有移动,这是为杂呢?其实,方法没有错,view也的确移动了,只是他移动的不是我们想要的东西。scrollTo,scrollBy方法移动的是view的content,即让view的内容移动,如果是在ViewGroup中使用scrollTo,scrollBy方法,那么移动的将是所有的子View,而如果在View中使用的话,就是view的内容,所以我们需要改一下我们之前的代码:

((View)getParent()).scrollBy(offSetX, offSetY);

这次是可以滑动了,但是我们发现,滑动的效果跟我们想象的不一样,完全相反了,这又是为什么呢?其实这是因为android中对于移动参考系选择的不同从而实现这样的效果,而我们想要实现我们滑动的效果,只需将偏移量设置为负值即可,代码如下:

((View) getParent()).scrollBy(-offSetX, -offSetY);

同样的在使用*对坐标时,使用scrollTo也可以达到这样的效果。

scroller
如果让一个View向右移动200的距离,使用上面的方式,大家应该发现了一个问题,就是移动都是瞬间完成的,没有那种慢慢平滑的感觉,所以呢,android就给我们提供了一个类,叫scroller类,使用该类就可以实现像动画一样平滑的效果。

其实它实现的原理跟前面的scrooTo,scrollBy方法实现view的滑动原理类似,它是将ACTION_MOVE移动的一段位移划分成N段小的偏移量,然后再每一个偏移量里面使用scrollBy方法来实现view的瞬间移动,这样在整体的效果上就实现了平滑的效果,说白了就是利用人眼的视觉暂留特性。

下面我们就来实现这么一个例子,移动view到某个位置,松开手指,view都吸附到左边位置,一般来说,使用Scroller实现滑动,需经过以下几个步骤:

初始化Scroller

//初始化Scroller,使用默认的滑动时长与插值器
mScroller = new Scroller(context);

重写computeScroll()方法

该方法是Scroller类的核心,系统会在绘制View的时候调用draw()方法中调用该方法,这个方法本质上是使用scrollTo方法,通过Scroller类可以获取到当前的滚动值,这样我们就可以实现平滑一定的效果了,一般模板代码如下:

@Override
public void computeScroll()
{
super.computeScroll();
//判断Scroller是否执行完成
if (mScroller.computeScrollOffset()) {
((View)getParent()).scrollTo(
mScroller.getCurrX(),
mScroller.getCurrY()
);
//调用invalidate()computeScroll()方法
invalidate();
}
}

Scroller类提供中的方法:

computeScrollOffset(): 判断是否完成了真个滑动

getCurrX(): 获取在x抽方向上当前滑动的距离

getCurrY(): 获取在y抽方向上当前滑动的距离

startScroll开启滑动

*后在需要使用平滑移动的事件中,使用Scroller类的startScroll()方法来开启滑动过程,startScroller()方法有两个重载的方法:

– public void startScroll(int startX, int startY, int dx, int dy)

– public void startScroll(int startX, int startY, int dx, int dy, int duration)

可以看到他们的区别只是多了duration这个参数,而这个是滑动的时长,如果没有使用默认时长,默认是250毫秒,而其他四个坐标则表示起始坐标与偏移量,可以通过getScrollX(),getScrollY()来获取父视图中content所滑动到的点的距离,不过要注意这个值的正负,它与scrollBy,scrollTo中说的是一样的。经过上面这三步,我们就可以实现Scroller的平滑一定了。

继续上面的例子,我们可以在onTouchEvent方法中监听ACTION_UP事件动作,调用startScroll方法,其代码如下:

case MotionEvent.ACTION_UP:
//第三步
//当手指离开时,执行滑动过程
ViewGroup viewGroup = (ViewGroup) getParent();
mScroller.startScroll(
viewGroup.getScrollX(),
viewGroup.getScrollY(),
-viewGroup.getScrollX(),
0,
800
);
//刷新布局,从而调用computeScroll方法
invalidate();
break;

属相动画
使用属性动画同样可以控制一个View的滑动,下面使用属相动画来实现上边的效果(关于属相动画,请关注其他的博文),代码如下:

case MotionEvent.ACTION_UP:
ViewGroup viewGroup = (ViewGroup) getParent();
//属性动画执行滑动
ObjectAnimator.ofFloat(this, “translationX”, viewGroup.getScrollX()).setDuration(500)
.start();
break;

ViewDragHelper
一看这个类的名字,我们就知道他是与拖拽有关的,猜的没错,通过这个类我们基本可以实现各种不同的滑动,拖放效果,他是非常强大的一个类,但是它也是*为复杂的,但是不要慌,只要你不断的练习,就可以数量的掌握它的使用技巧。下面我们使用这个类来时实现类似于QQ滑动侧边栏的效果,相信广大朋友们多与这个现象是很熟悉的吧。

先来看看使用的步骤是如何的:

初始化ViewDragHelper

ViewDragHelper这个类通常是定义在一个ViewGroup的内部,并通过静态方法进行初始化,代码如下:

//初始化ViewDragHelper
viewDragHelper = ViewDragHelper.create(this,callback);

它的*个参数是要监听的View,通常是一个ViewGroup,第二个参数是一个Callback回调,它是整个ViewDragHelper的逻辑核心,后面进行具体介绍。

拦截事件

重写拦截事件onInterceptTouchEvent与onTouchEvent方法,将事件传递交给ViewDragHelper进行处理,代码如下:

@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
//2. 将事件交给ViewDragHelper
return viewDragHelper.shouldInterceptTouchEvent(ev);
}

@Override
public boolean onTouchEvent(MotionEvent event)
{
//2. 将触摸事件传递给ViewDragHelper,不可少
viewDragHelper.processTouchEvent(event);
return true;
}

处理computeScroll()方法

前面我们在使用Scroller类的时候,重写过该方法,在这里我们也需要重写该方法,因为ViewDragHelper内部也是使用Scroller类来实现的,代码如下:

//3. 重写computeScroll
@Override
public void computeScroll()
{
//持续平滑动画 (高频率调用)
if (viewDragHelper.continueSettling(true))
// 如果返回true, 动画还需要继续执行
ViewCompat.postInvalidateOnAnimation(this);
}

处理回调Callback

通过如下代码创建一个Callback:

private ViewDragHelper.Callback callback = new ViewDragHelper.Callback()
{
@Override
//此方法中可以指定在创建ViewDragHelper时,参数ViewParent中的那些子View可以被移动
//根据返回结果决定当前child是否可以拖拽
// child 当前被拖拽的View
// pointerId 区分多点触摸的id
public boolean tryCaptureView(View child, int pointerId)
{
//如果当前触摸的view是mMainView时开始检测
return mMainView == child;
}

@Override
//水平方向的滑动
// 根据建议值 修正将要移动到的(横向)位置 (重要)
// 此时没有发生真正的移动
public int clampViewPositionHorizontal(View child, int left, int dx)
{
//返回要滑动的距离,默认返回0,既不滑动
//参数参考clampViewPositionVertical
f (child == mMainView)
{
if (left > 300)
{
left = 300;
}
if (left < 0)
{
left = 0;
}
}
return left;
}

@Override
//垂直方向的滑动
// 根据建议值 修正将要移动到的(纵向)位置 (重要)
// 此时没有发生真正的移动
public int clampViewPositionVertical(View child, int top, int dy)
{
//top : 垂直向上child滑动的距离,
//dy: 表示比较前一次的增量,通常只需返回top即可,如果需要精确计算padding等属性的话,就需要对left进行处理
return super.clampViewPositionVertical(child, top, dy); //0
}
};

到这里就可以拖拽mMainView移动了。

下面我们继续来优化这个代码,还记得之前我们使用Scroller时,当手指离开屏幕后,子view会吸附到左边位置,当时我们监听ACTION_UP,然后调用startScroll来实现的,这里我们使用ViewDragHelper来实现。

在ViewDragHelper.Callback中,系统提供了这么一个方法—onViewReleased(),我们可以通过重写这个方法,来实现之前的操作,当然这个方法内部也是通过Scroller来实现的,这也是为什么我们要重写computeScroll方法的原因,实现代码如下:

@Override
//拖动结束时调用
public void onViewReleased(View releasedChild, float xvel, float yvel)
{
if (mMainView.getLeft() < 150)
{
// 触发一个平滑动画,关闭菜单,相当于Scroll的startScroll方法
if (viewDragHelper.smoothSlideViewTo(mMainView, 0, 0))
{
// 返回true代表还没有移动到指定位置, 需要刷新界面.
// 参数传this(child所在的ViewGroup)
ViewCompat.postInvalidateOnAnimation(DragLayout.this);
}
}
else
{
//打开菜单
if (viewDragHelper.smoothSlideViewTo(mMainView, 300, 0)) ;
{
ViewCompat.postInvalidateOnAnimation(DragLayout.this);
}
}
super.onViewReleased(releasedChild, xvel, yvel);
}

 

当滑动的距离小于150时,mMainView回到原来的位置,当大于150时,滑动到300的位置,相当于打开了mMenuView,而且滑动的时候是很平滑的。此外还有一些方法:

@Override
public void onViewCaptured(View capturedChild, int activePointerId)
{
// 当capturedChild被捕获时,调用.
super.onViewCaptured(capturedChild, activePointerId);
}

@Override
public int getViewHorizontalDragRange(View child)
{
// 返回拖拽的范围, 不对拖拽进行真正的限制. 仅仅决定了动画执行速度
return 300;
}

@Override
//当View位置改变的时候, 处理要做的事情 (更新状态, 伴随动画, 重绘界面)
// 此时,View已经发生了位置的改变
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy)
{
// changedView 改变位置的View
// left 新的左边值
// dx 水平方向变化量
super.onViewPositionChanged(changedView, left, top, dx, dy);
}

说明:里面还有很多关于处理各种事件方法的定义,如:

onViewCaptured():用户触摸到view后回调

onViewDragStateChanged(state):这个事件在拖拽状态改变时回调,比如:idle,dragging等状态

onViewPositionChanged():这个是在位置改变的时候回调,常用于滑动时伴随动画的实现效果等

对于里面的方法,如果不知道什么意思,则可以打印log,看看参数的意思。

总结
这里介绍的就是android实现滑动的七种方法,至于使用哪一种好,就要结合具体的项目需求场景了,毕竟硬生生的实现这个效果,而不管用户的使用体验式不切实际的,这里面个人觉得比较重要的是Scroller类的使用。属性动画以及ViewDragHelper类,特别是*后一个,也是*难*复杂的,但也是甩的*多的。

终于写完了,好累的赶脚~~~
————————————————