手把手实现腾讯qq拖拽删去效果(一)
qq拖拽删除的效果,简单又好用,今天我就叫大家实现吧。
这个滑动效果,有何难点了,就是响应每行的点击事件了,为了完成这个任务,并且能够实现动画的效果了,我重写了一个slideview这个控件,这个控件是干什么的了,是一个类似于viewflipper带动画的翻页控件了。它又是任何布局,任何控制了。
首先,我们赏析一下它的布局文件:
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" > <LinearLayout
android:id="@+id/view_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
</LinearLayout> <RelativeLayout
android:id="@+id/holder"
android:layout_width="120dp"
android:layout_height="match_parent"
android:clickable="true"
android:background="@drawable/delete_holder_bg"> <TextView
android:id="@+id/delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/delete_icon_normal"
android:layout_centerInParent="true"
android:gravity="center"
android:textColor="@color/floralwhite"
android:text="删除" />
</RelativeLayout> </merge>
由布局文件,可得知:
①由一对<merge>....</merge>标签包裹了里面的容器,merge标签是什么了,又有什么作用了。可以使用<merge>标签,它将它里面嵌套的view直接include到其父layout中,而没有再加一层view group,因此减小了深度,提高了速度。在这里了,我们就是将一个linearlayout的线性表局文件和relative布局文件嵌套其中了。
②relativelayout是显示相应的删除的按钮,而linearlayout主要是显示需要加载数据的值。
具体的说明,请见下图:
这里我们首先说明了布局文件,接下来就是控制文件了。
控制文件的代码如何,我们来瞧一瞧:
package com.routemap_infomation.utils; import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Scroller;
import android.widget.TextView; import com.routemap_infomation.myfocus.R; public class SlideView extends LinearLayout { private static final String TAG = "SlideView"; private Context mContext;
private LinearLayout mViewContent;
private RelativeLayout mHolder;
private Scroller mScroller;
private OnSlideListener mOnSlideListener; private int mHolderWidth = 100; private int mLastX = 0;
private int mLastY = 0;
private static final int TAN = 2; public interface OnSlideListener {
public static final int SLIDE_STATUS_OFF = 0;
public static final int SLIDE_STATUS_START_SCROLL = 1;
public static final int SLIDE_STATUS_ON = 2; /**
* @param view current SlideView
* @param status SLIDE_STATUS_ON or SLIDE_STATUS_OFF
*/
public void onSlide(View view, int status);
} public SlideView(Context context) {
super(context);
initView();
} public SlideView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
} private void initView() {
mContext = getContext();
mScroller = new Scroller(mContext); setOrientation(LinearLayout.HORIZONTAL);
View.inflate(mContext, R.layout.delete_button, this);
mViewContent = (LinearLayout) findViewById(R.id.view_content);
mHolderWidth = Math.round(TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, mHolderWidth, getResources()
.getDisplayMetrics()));
} public void setButtonText(CharSequence text) {
((TextView)findViewById(R.id.delete)).setText(text);
} public void setContentView(View view) {
mViewContent.addView(view);
} public void setOnSlideListener(OnSlideListener onSlideListener) {
mOnSlideListener = onSlideListener;
} public void shrink() {
if (getScrollX() != 0) {
this.smoothScrollTo(0, 0);
}
} public boolean onRequireTouchEvent(MotionEvent event) { int x = (int) event.getX();
int y = (int) event.getY();
int scrollX = getScrollX();
Log.d(TAG, "x=" + x + " y=" + y); switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: { if (!mScroller.isFinished()) {
mScroller.abortAnimation();
}
if (mOnSlideListener != null) {
mOnSlideListener.onSlide(this,
OnSlideListener.SLIDE_STATUS_START_SCROLL);
}
break;
}
case MotionEvent.ACTION_MOVE: { int deltaX = x - mLastX;
int deltaY = y - mLastY;
if (Math.abs(deltaX) < Math.abs(deltaY) * TAN) {
break;
} int newScrollX = scrollX - deltaX;
if (deltaX != 0) {
if (newScrollX < 0) {
newScrollX = 0;
} else if (newScrollX > mHolderWidth) {
newScrollX = mHolderWidth;
}
this.scrollTo(newScrollX, 0);
}
break;
}
case MotionEvent.ACTION_UP: { int newScrollX = 0;
if (scrollX - mHolderWidth * 0.75 > 0) {
newScrollX = mHolderWidth;
}
this.smoothScrollTo(newScrollX, 0);
if (mOnSlideListener != null) {
mOnSlideListener.onSlide(this,
newScrollX == 0 ? OnSlideListener.SLIDE_STATUS_OFF
: OnSlideListener.SLIDE_STATUS_ON);
return false;
}
// break;
}
default:
break;
} mLastX = x;
mLastY = y;
return true;
} private void smoothScrollTo(int destX, int destY) {
// 缓慢滚动到指定位置
int scrollX = getScrollX();
int delta = destX - scrollX;
mScroller.startScroll(scrollX, 0, delta, 0, Math.abs(delta) * 3);
invalidate();
} @Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
} }
由代码我们可以下这样的结论了:
①这个控件其实本质是一个线性布局(Linearlayout)控件,因此就具有了linearlayout的属性。
②我上文说过这个控件是为了实现一个viewflipper翻页动画效果,因此需要一个动画效果,这里,我没有做自身的动画,而是通过了scroller本身滑动带有的动画效果。
③因为是拖拽,所以监听屏幕的触摸事件也是理所当然了,因此需要处理好触摸按下(down),触摸移动(move),抬起(up)的事件,对其相应事件下,scroller(滑动条)移动的距离需要进行监听。
④由于要移动控件,移动后,相应的控件需要进行了重回。
这就是我实现了拖拽效果的一利器,今天就介绍到这里了。下节,来说明吧它如何整合到自定义的下拉列表中去。
手把手实现腾讯qq拖拽删去效果(一)的更多相关文章
- 手把手实现腾讯qq拖拽删去效果(二)
这节,就一个任务如何把上节自定义的翻页动画控件整进下拉列表中去. 由于是自定义的下拉列表控件,我们需要自定义能够上啦下滑的listview,这势必会造成这个问题,上拉刷新要响应相应touch事件,拖拽 ...
- js仿QQ拖拽删除
原生js实现仿QQ拖拽删除交互,无需任何依赖. 项目演示请看这里, gitHub请移步这里. 由于源码很长,所以贴到最下面了. 效果截图如下: 核心思想呢,就是点击圆点的时候全屏覆盖个canvas,在 ...
- reactnative实现qq聊天消息气泡拖拽消失效果
前言(可跳过) 我在开发自己的APP时遇到了一个类似于qq聊天消息气泡拖拽消息的需求,因为在网上没有找到相关的组件,所以自己动手实现了一下 需求:对聊天消息气泡拖拽到一定长度松开时该气泡会消失(可自行 ...
- react实现的点击拖拽元素效果
之前用vue做日程管理组件的时候,用到了点击拖拽的效果,即点击元素,鼠标移动到哪里,元素移动到哪里,鼠标松开,拖拽停止,现在在弄react,于是也在想实现这个效果,经过一番折腾,效果出来了,代码如下: ...
- js实现音量拖拽的效果模拟
<!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>js ...
- ToolStrip控件左右拖拽移动效果实现
1.主窗体下部添加一个Panel乘放ToolStrip控件以实现ToolStrip在窗体下部定位.2.当ToolStrip控件中子控件超出屏幕时,拖动控件可以实现滑动效果.拖动到控件边缘距窗体边缘1/ ...
- iOS 未读消息角标 仿QQ拖拽 简单灵活 支持xib(源码)
一.效果 二.简单用法 超级简单,2行代码集成:xib可0代码集成,只需拖一个view关联LFBadge类即可 //一般view上加角标 _badge1 = [[LFBadge alloc] init ...
- Javascript实现重力弹跳拖拽运动效果
声明: By:GenialX 个人主页:胡旭博客 - www.ihuxu.com QQ:2252065614 演示地址: http://www.ihuxu.com/project/gcdmove/ 调 ...
- 拖拽碰撞效果,高级浏览器下全部搞定(ie6-8还没有搞定)
<!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8& ...
随机推荐
- hihoCoder.1457.后缀自动机四 重复旋律7(广义后缀自动机)
题目链接 假设我们知道一个节点表示的子串的和sum,表示的串的个数cnt,那么它会给向数字x转移的节点p贡献 \(sum\times 10+c\times cnt\) 的和. 建广义SAM,按拓扑序正 ...
- NOIP练习赛题目5
小象涂色 难度级别:C: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 小象喜欢为箱子涂色.小象现在有c种颜色,编号为0~c-1:还有n个箱 ...
- 使用Xcode打包上传APP
1.打开xcode,进入product->Scheme->EditScheme,找到Archive,最上面的设备选择IOSDevice,在BuildConfiguration中选中Rele ...
- CentOS增加用户到sudo用户组
1.直接增加到wheel用户组 usermod -a -G wheel username 2.编辑/etc/sudoers文件增加 echo "username ALL=(ALL) ALL& ...
- word如何插入和删除脚注,尾注
在我们日常使用word时,经常会使用到脚注/尾注来对文中某些文字或内容进行注释或是重点说明,效果挺好,挺直观和明显.但是很多人并不会使用,特别是当需要删除脚注事,就特别苦恼了,那根小横线怎么也删除不掉 ...
- 怎样把XP系统装到USB里?
怎么样在usb(usb闪存)里面装XP系统? 就是把usb当硬盘用 不买硬盘. U盘肯定装不了系统,装进去了也肯定蓝屏.为什么?因为USB得数据传输太慢,不会超过10M/S的,而你的IDE口或者SAT ...
- 【CentOS】centos如何修改你的主机名
转载地址:https://www.linuxidc.com/Linux/2014-11/109238.htm ============================================= ...
- 【linux】linux 下 shell命令 执行结果赋值给变量【两种方式】
方法1:[通用方法] 使用Tab键上面的反引号 例子如下: find命令 模糊查询在/apps/swapping目录下 查找 文件名中包含swapping并且以.jar结尾的文件 使用反引号 引住命令 ...
- 【docker】【Gitlab】gitlab中clone项目时,IP地址是一串数字(内网Gitlab的IP地址不正确)的问题解决
首次在内网搭建Gitlab环境,在成功后在Gitlab上新建了一个项目. 然而在IDEA上clone项目时发现,项目地址如下: git@0096ce63c43f:root/jump.git 或者这样 ...
- 虚拟化(三):vsphere套件的安装注意及使用
虚拟化(一):虚拟化及vmware产品介绍 虚拟化(二):虚拟化及vmware workstation产品使用 虚拟化(五):vsphere高可用群集与容错 vsphere套件里面基本的组件有e ...