仿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效果如图: 图中我们可以看到,动画处的头像和文字是一起的,即同时并且是整体,注意,是整体进行缩放的 ...
随机推荐
- Mocking framework
[译] 什么是Mocking framework?它有什么用? 原位地址:http://codetunnel.com/blog/post/what-is-a-mocking-framework-why ...
- WCF小实例以及三种宿主
WCF小实例以及三种宿主 最近一直在学习WCF相关知识,下面将通过一个小实例对所学的知识进行简单的回顾:本实例是一个简单三层操作数据库,并且也简单实现的三种宿主(控制台宿主,IIS宿主以及Window ...
- Java网络请求getInputStream异常
今天调试网络请求部分时,当getInputStream失败时直接抛出异常.解决方法时在getInputStream之前获取ResponseCode if( connection.getResponse ...
- 彩蛋 Python之道
彩蛋 Python之道 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 使用下面的语句可以调出Python中的一个彩蛋, impo ...
- TOGAF架构内容框架之内容元模型(上)
TOGAF架构内容框架之内容元模型(上) 2. 内容元模型(Content Metamodel) 在TOGAF的眼中,企业架构是以一系列架构构建块为基础的,并将目录.矩阵和图形作为其具体展现方式.如果 ...
- Linux kernel中网络设备的管理
kernel中使用net_device结构来描述网络设备,这个结构是网络驱动及接口层中最重要的结构.该结构不仅描述了接口方面的信息,还包括硬件信息,致使该结构很大很复杂.通过这个结构,内核在底层的网络 ...
- 如何制作一个类似Tiny Wings的游戏 Cocos2d-x 2.1.4
在第一篇<如何使用CCRenderTexture创建动态纹理>基础上,增加创建动态山丘,原文<How To Create A Game Like Tiny Wings with Co ...
- SharePoint Access Service-PowerShell
1. 配置应用程序Log文件大小 Set-SPAccessServiceApplication –Identity "Access Services" –ApplicationLo ...
- HTTPCLIENT抓取网页内容
通过httpclient抓取网页信息. public class SnippetHtml{ /** * 通过url获取网站html * @param url 网站url */ public Strin ...
- 捕鱼达人代码例子下载地址 mac版
捕鱼达人代码例子下载地址 mac版: http://pan.baidu.com/share/link?shareid=1431898404&uk=3189484501