仿qq的条目抽屉动画效果_ViewDragHelper

GitHub地址:
https://github.com/OOOOOldZhu/DrawerItemView
import android.content.Context;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
public class SwipeLayout extends FrameLayout {
private View content;
private View delete;
ViewDragHelper dragHelper;
public SwipeLayout(Context context) {
this(context, null);
}
public SwipeLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SwipeLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
//初始化ViewDragHelper
dragHelper = ViewDragHelper.create(this, callback);
}
//只有完成系统对xml文件完成最后标签的解析,才能获得子控件
@Override
protected void onFinishInflate() {
super.onFinishInflate();
content = getChildAt(0);
delete = getChildAt(1);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
content.layout(0, 0, content.getMeasuredWidth(),
content.getMeasuredHeight());
int L = content.getRight();
//content(右下角)的right(距原点的x距离)即为 delete控件的左上角的x坐标
delete.layout(L, 0, L + delete.getMeasuredWidth(),
delete.getMeasuredHeight());
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
//让helper处理拦截事件
boolean result = dragHelper.shouldInterceptTouchEvent(ev);
return result;
}
float downX,downY;
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
float moveX = event.getX();
float moveY = event.getY();
//计算移动的距离
float dx = moveX - downX;
float dy = moveY - downY;
//判断到底偏向于哪个方向
if(Math.abs(dx)>Math.abs(dy)){
//说明是偏向水平方向,那么就认为用户想滑动条目,此时应该让listview不要拦截
requestDisallowInterceptTouchEvent(true);
}
break;
case MotionEvent.ACTION_UP:
break;
}
dragHelper.processTouchEvent(event);
return true;
}
// 回调方法
ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(View child, int pointerId) {
return true;
}
@Override
public int getViewHorizontalDragRange(View child) {
return 1;
}
//修正子控件的位置坐标的方法
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制content
if(child==content){
if(left>0){
left = 0;
}else if(left<-delete.getMeasuredWidth()){
left = -delete.getMeasuredWidth();
}
}else if(child==delete){
//限制delete
if(left>content.getMeasuredWidth()){
left = content.getMeasuredWidth();
}else if(left<(content.getMeasuredWidth()-
delete.getMeasuredWidth()))
{
left = (content.getMeasuredWidth()-
delete.getMeasuredWidth());
}
}
return left;
}
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
//如果移动的是content,那么让delete伴随移动
if(changedView==content){
// int newLeft = delete.getLeft()+dx;
// delete.layout(newLeft,0,newLeft+delete.getMeasuredWidth(),delete.getMeasuredHeight());
ViewCompat.offsetLeftAndRight(delete,dx);
}else if(changedView==delete){
//让content进行伴随移动
ViewCompat.offsetLeftAndRight(content,dx);
}
//回调接口的方法
if(listener!=null){
if(content.getLeft()==0){
listener.onClose(SwipeLayout.this);
}else if(content.getLeft()==-delete.getMeasuredWidth()){
listener.onOpen(SwipeLayout.this);
}
}
}
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
if(content.getLeft()>-delete.getMeasuredWidth()/2){
//关闭抽屉
closeLayout();
}else {
//打开抽屉
openLayout();
}
}
};
/**
* 打开
*/
public void openLayout() {
dragHelper.smoothSlideViewTo(content,-delete.
getMeasuredWidth(),0);
ViewCompat.postInvalidateOnAnimation(this);
}
/**
* 关闭
*/
public void closeLayout() {
dragHelper.smoothSlideViewTo(content,0,0);
ViewCompat.postInvalidateOnAnimation(this);
}
@Override
public void computeScroll() {
super.computeScroll();
if(dragHelper.continueSettling(true)){
ViewCompat.postInvalidateOnAnimation(this);
}
}
private OnSwipeListener listener;
public void setOnSwipeListener(OnSwipeListener listener){
this.listener = listener;
}
public interface OnSwipeListener{
void onOpen(SwipeLayout currentLayout);
void onClose(SwipeLayout currentLayout);
}
}
MainActivity中:
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import butterknife.Bind;
import butterknife.ButterKnife;
public class MainActivity extends AppCompatActivity {
private ListView listview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listview = (ListView) findViewById(R.id.listview);
listview.setAdapter(new MyAdapter());
//监听listview的滚动
listview.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if(openedLayout!=null){
openedLayout.closeLayout();
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
}
});
}
SwipeLayout openedLayout;//用来记录打开的SwipeLayout
class MyAdapter extends BaseAdapter implements
SwipeLayout.OnSwipeListener{
@Override
public int getCount() {
return Constant.NAMES.length;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
MyHolder myHolder = null;
if(convertView==null){
convertView = View.inflate(parent.getContext(), R.layout.adapter_list,
null);
myHolder = new MyHolder(convertView);
convertView.setTag(myHolder);
}else {
myHolder = (MyHolder) convertView.getTag();
}
//绑定数据
myHolder.tvName.setText(Constant.NAMES[position]);
//设置监听器
myHolder.swipeLayout.setOnSwipeListener(this);
return convertView;
}
@Override
public void onOpen(SwipeLayout currentLayout) {
//应该关闭当前已经打开的
if(openedLayout!=null && openedLayout!=currentLayout){
openedLayout.closeLayout();
}
openedLayout = currentLayout;
}
@Override
public void onClose(SwipeLayout currentLayout) {
if(openedLayout==currentLayout){
openedLayout = null;
}
}
}
static class MyHolder {
@Bind(R.id.tv_name)
TextView tvName;
@Bind(R.id.tv_delete)
TextView tvDelete;
@Bind(R.id.swipeLayout)
SwipeLayout swipeLayout;
MyHolder(View view) {
ButterKnife.bind(this, view);
}
}
}
仿qq的条目抽屉动画效果_ViewDragHelper的更多相关文章
- 【Android UI设计与开发】第03期:引导界面(三)仿微信引导界面以及动画效果
基于前两篇比较简单的实例做铺垫之后,这一篇我们来实现一个稍微复杂一点的引导界面的效果,当然也只是稍微复杂了一点,对于会的人来说当然还是so easy!正所谓会者不难,难者不会,大概说的就是这个意思了吧 ...
- android开发学习 ------- 仿QQ侧滑效果的实现
需要做一个仿QQ侧滑删除的一个效果: 一开始是毫无头绪,百度找思路,找到 https://blog.csdn.net/xiaxiazaizai01/article/details/53036994 ...
- Android高仿qq及微信底部菜单的几种实现方式
最近项目没那么忙,想着开发app的话,有很多都是重复,既然是重复的,那就没有必要每次都去写,所以就想着写一个app通用的基本框架,这里说的框架不是什么MVC,MVP,MVVM这种,而是app开发的通用 ...
- wing带你玩转自定义view系列(2) 简单模仿qq未读消息去除效果
上一篇介绍了贝塞尔曲线的简单应用 仿360内存清理效果 这一篇带来一个 两条贝塞尔曲线的应用 : 仿qq未读消息去除效果. 转载请注明出处:http://blog.csdn.net/wingicho ...
- Fragment,仿QQ空间
转载请注明出处:http://blog.csdn.net/yangyu20121224/article/details/9023451 在今天的这篇文章当中,我依然会以实战加理论结合 ...
- Android仿QQ窗口的抖动的动画效果
就是仿照QQ窗口的抖动效果,在项目的res下创建anim文件夹,再创建两个xml文件:cycle.xml . myanim.xml cycle.xml : <?xml version ...
- Android -- 自定义ViewGroup+贝塞尔+属性动画实现仿QQ点赞效果
1,昨天我们写了篇简单的贝塞尔曲线的应用,今天和大家一起写一个QQ名片上常用的给别人点赞的效果,实现效果图如下: 红心的图片比较丑,见谅见谅(哈哈哈哈哈哈).... 2,实现的思路和原理 从上面的效果 ...
- android 自定义scrollview 仿QQ空间效果 下拉伸缩顶部图片,上拉回弹 上拉滚动顶部title 颜色渐变
首先要知道 自定义scrollview 仿QQ效果 下拉伸缩放大顶部图片 的原理是监听ontouch事件,在MotionEvent.ACTION_MOVE事件时候,使用不同倍数的系数,重置布局位置[ ...
- 安卓仿QQ红包领取详情界面动画
为了能清楚的看到这个效果,本人不惜几次花费重金给众群叼发放红包,来查看红包领取详情界面的动画效果,QQ效果如图: 图中我们可以看到,动画处的头像和文字是一起的,即同时并且是整体,注意,是整体进行缩放的 ...
随机推荐
- 迟到的 WPF 学习 —— 入门
之所以说"迟到的",是因为我太晚才开始学习 WPF 了,之前 WPF 刚发布的时候有过粗浅了解,那时的 WPF 还非常简陋,VS 提供的内置控件十分匮乏,让我这样的非常依赖 Win ...
- 如何将 Area 中的 Controller 放到独立的程序集?
目录 背景如何将 Area 中的 Controller 放到独立的程序集?备注 背景返回目录 本文假设您已经熟悉了 ASP.NET MVC 的常规开发方式.执行模型和关键扩展点,这里主要说一下如何使用 ...
- SQLSERVER数据库自动备份工具SQLBackupAndFTP(功能全面)
挺好用的SQLSERVER数据库自动备份工具SQLBackupAndFTP(功能全面) 这个工具主要就是自动备份数据库,一键还原数据库,发送备份数据库日志报告到邮箱,自动压缩备份好的数据库 定期执行数 ...
- 用c#实现与飞环语音卡的交互
现在很多企业都采用freeswitch搭建的软交换来实现通话,主要优势成本低吞吐量大,但是语音卡的通话质量还是瑞胜一筹. 去年有机会在朋友公司里帮忙开发与软交换交互的上层服务及接口,在开发过程中稍微研 ...
- 单一职责原则SRP
定义: There should nerver be more then one reason for a class to change. 优点: 1.类的复杂性降低,实现什么职责都有清晰明确的定义 ...
- 一步一步深入spring(6)--使用基于XML配置的spring实现的AOP
上节我们提到了使用基于注解实现的AOP,这节我们将用基于xml配置的方式来实现的AOP. 1.首先建立一个类,作为切面类,这个类主要用来实现注解中各种通知要实现的方法. package com.yan ...
- C#中WindowsForm常见控件的运用
C#中WindowsForm常见控件的运用 -- 1.button(曹操,贡天子以令不臣): 属性;text:我们经常可以看见将按钮命名为“登入”,在其属性面板里面编辑text即可:如下图: ...
- java自动生成略缩图
当你要做一个图库的项目时,对图片大小.像素的控制是首先需要解决的难题. 本篇文章,在前辈的经验基础上,分别对单图生成略缩图和批量生成略缩图做个小结. 一.单图生成略缩图 单图经过重新绘制,生成新的图片 ...
- OpenRisc-34-ORPSoC跑eCos实验
引言 ORPSoC目前支持好几种OS,除了前面一直介绍的linux,还支持eCos,eCos是RTOS,如果你的系统对时间的要求比较高,那eCos会是一个不错的选择. 本小节就简单介绍一下,在ORPS ...
- iOS 指南针的制作 附带源码
iOS 指南针的制作 附带源码 代码下载地址: http://vdisk.weibo.com/s/HK4yE http://pan.baidu.com/share/link?shareid=7 ...