精华内容
下载资源
问答
  • 高仿QQ消息,可以下拉刷新带小红点

    千次阅读 2015-12-08 11:06:32
    最近在做即时通讯这一块,老板知道怎么想的,反正完全是照着QQ做的,而我个人又非常喜欢qq侧滑操作这个效果,于是想找来用,但是翻遍了网络,没有一个像样的例子,有相似的也是各种bug各种限制,我也崩溃啊,没...

    最近在做即时通讯这一块,老板不知道怎么想的,反正完全是照着QQ做的,而我个人又非常喜欢qq侧滑操作这个效果,于是想找来用,但是翻遍了网络,没有一个像样的例子,有相似的也是各种bug各种限制,我也崩溃啊,没办法只好自己搞一个了。不多说上效果图:

    高仿QQ消息界面功能

    具体实现呢,是自定义的listview来做的,本来的思路是自定义item的根布局来做,结果出来之后,事件的分发处理,特别不好弄,各种不流畅。

    于是改用自定义listview,结果很喜人,个人觉得比较完美,支持3.0以下,
    由于是属性动画需要支持到3.0以下,所以使用了nineoldandroid这个开源的属性动画库。

    下面看代码:

    public class InfoListView extends ListView {
        private int mScreenWidth;    // 屏幕宽度
        private float mDownX;            // 按下点的x值
        private float mDownY;            // 按下点的y值
        private int mActionViewWidth;// 操作view的宽度
    
        /**
         * 执行动画的时间
         */
        protected long mAnimationTime = 150;
    
        private boolean isActionViewShow = false;    // 删除按钮是否正在显示
    
        private ViewGroup mPointChild;    // 当前处理的item
        private LinearLayout.LayoutParams mLayoutParams;    // 当前处理的item的LayoutParams
    
        private int touchSlop;//最小偏移量超过这个值才处理滑动事件
    
        private float scroll;//偏移的距离
    
        private int openedIntemPosition = -1;//记录已经打开的item的位置
    
        private int childPosition;//手指落下位置的item的position
    
        private boolean iswiping = false;//手指是否正在滑动
    
        private boolean isDownToNormal = false;//判断之前是否是手指落下导致消失。
    
        private boolean isUPToNormal = false;//判断之前是否是手指离开导致消失。
    
        private long lastTime;//计算手指两次的触摸间隔
    
        public InfoListView(Context context) {
            this(context, null);
        }
    
        public InfoListView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public InfoListView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
    
            // 获取屏幕宽度
            WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            DisplayMetrics dm = new DisplayMetrics();
            wm.getDefaultDisplay().getMetrics(dm);
            mScreenWidth = dm.widthPixels;
            final ViewConfiguration configuration = ViewConfiguration.get(getContext());
            touchSlop = configuration.getScaledTouchSlop();
    
        }
    
    
        @Override
        public boolean onTouchEvent(MotionEvent ev) {
    
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    performActionDown(ev);
                    break;
                case MotionEvent.ACTION_MOVE:
                    return performActionMove(ev);
                case MotionEvent.ACTION_UP:
                    performActionUp(ev);
                    break;
            }
    
    
            return super.onTouchEvent(ev);
    
        }
    
        // 处理action_down事件
        private void performActionDown(MotionEvent ev) {
    
    
            //如果触摸间隔小于100MS 不让进来~
            if (System.currentTimeMillis() - lastTime <= mAnimationTime) {
    
                lastTime = System.currentTimeMillis();
                return;
            }
    
            lastTime = System.currentTimeMillis();
    
            mDownX = ev.getX();
            mDownY = ev.getY();
    
            if (isActionViewShow) {
    
                childPosition = pointToPosition((int) mDownX, (int) mDownY);
    
                if (childPosition == AdapterView.INVALID_POSITION) {
    
                    return;
    
                }
                if ((openedIntemPosition != childPosition - getFirstVisiblePosition())) {
    
                    //全部恢复初始值不作响应
                    turnToNormal();
                    isDownToNormal = true;
                    mDownX = -1;
                    mDownY = -1;
                    return;
                }
    
            }
    
            if ((!isActionViewShow && openedIntemPosition == -1)) {
                // 获取当前点的item
                childPosition = pointToPosition((int) mDownX, (int) mDownY);
    
                if (childPosition == AdapterView.INVALID_POSITION) {
    
                    return;
    
                }
    
                openedIntemPosition = childPosition - getFirstVisiblePosition();
    
                mPointChild = (ViewGroup) getChildAt(openedIntemPosition);
                // 获取操作view宽度
                mActionViewWidth = mPointChild.getChildAt(1).getLayoutParams().width;
    
    
                mLayoutParams = (LinearLayout.LayoutParams) mPointChild.getChildAt(0)
                        .getLayoutParams();
                // 为什么要重新设置layout_width 等于屏幕宽度
                // 因为match_parent时,不管你怎么滑,都不会显示删除按钮
                // why? 因为match_parent时,ViewGroup就不去布局剩下的view
                mLayoutParams.width = mScreenWidth;
                mPointChild.getChildAt(0).setLayoutParams(mLayoutParams);
    
            }
    
        }
    
        // 处理action_move事件
        private boolean performActionMove(MotionEvent ev) {
    
    
            if ((Math.abs(ev.getX() - mDownX) > touchSlop
                    && Math.abs(ev.getY() - mDownY) < touchSlop)
                    || (Math.abs(ev.getX() - mDownX) > touchSlop
                    && Math.abs(ev.getY() - mDownY) > touchSlop
                    && (Math.abs(ev.getX() - mDownX) > Math.abs(ev.getY() - mDownY)))) {
    
    
                iswiping = true;
    
                //当手指滑动item,取消item的点击事件,不然我们滑动Item也伴随着item点击事件的发生
                MotionEvent cancelEvent = MotionEvent.obtain(ev);
                cancelEvent.setAction(MotionEvent.ACTION_CANCEL |
                        (ev.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
                onTouchEvent(cancelEvent);
    
            }
    
            if (isActionViewShow) {
    
                childPosition = pointToPosition((int) mDownX, (int) mDownY);
    
                if (childPosition == AdapterView.INVALID_POSITION) {
    
                    return true;
    
                }
                if ((openedIntemPosition != childPosition - getFirstVisiblePosition())) {
    
                    //全部恢复初始值不作响应
                    turnToNormal();
                    isDownToNormal = true;
                    mDownX = -1;
                    mDownY = -1;
                    iswiping = false;
                    return true;
                }
    
            }
    
    
            if (iswiping) {
    
                scroll = ev.getX() - mDownX;
    
                if (Math.abs(scroll) <= mActionViewWidth) {
    
                    if ((scroll <= 0 && !isActionViewShow)) {
    
    
                        ViewHelper.setTranslationX(mPointChild.getChildAt(0), scroll);
    
                        ViewHelper.setTranslationX(mPointChild.getChildAt(1), scroll);
    
    
                    } else if ((scroll >= 0 && isActionViewShow && openedIntemPosition != -1)) {
    
                        ViewHelper.setTranslationX(mPointChild.getChildAt(0), (scroll - mActionViewWidth));
                        ViewHelper.setTranslationX(mPointChild.getChildAt(1), (scroll - mActionViewWidth));
    
    
                    }
    
                }
    
                return true;
            }
    
            return super.onTouchEvent(ev);
    
        }
    
    
        // 处理action_up事件
        private void performActionUp(MotionEvent ev) {
    
    
            if (!iswiping) {
    
                if (isActionViewShow && openedIntemPosition != -1) {
    
                    isUPToNormal = true;
                    turnToNormal();
                } else {
    
                    turnToNormal();
                }
    
    
                return;
            }
    
    
            scroll = ev.getX() - mDownX;
            // 偏移量大于操作view的一半,则显示
            // 否则恢复默认
            //向左滑动
    
    
            if (scroll < 0) {
    
    
                if ((-scroll >= mActionViewWidth / 4) && !isActionViewShow) {
    
                    show();
    
                } else if ((-scroll < mActionViewWidth / 4) || ((-scroll >= mActionViewWidth / 4) && isActionViewShow)) {
    
                    if (isActionViewShow) {
    
                        childPosition = pointToPosition((int) mDownX, (int) mDownY);
    
                        if (childPosition == AdapterView.INVALID_POSITION) {
    
                            return;
    
                        }
                        if (openedIntemPosition == childPosition - getFirstVisiblePosition()) {
    
                            return;
                        }
    
                    }
    
                    turnToNormal();
    
                }
    
            } else if (scroll > 0) {//向右滑动
    
    
                if (scroll < mActionViewWidth / 4 && isActionViewShow && openedIntemPosition != -1) {
    
                    show();
    
                } else if (scroll >= mActionViewWidth / 4 && isActionViewShow && openedIntemPosition != -1) {
    
                    turnToNormal();
    
                } else {
    
                    //如果没有展开的其它情况全部恢复原样
                    turnToNormal();
    
                }
    
            }
    
    
            iswiping = false;
    
    
        }
    
    
        @Override
        public boolean performItemClick(View view, int position, long id) {
    
            //当有展开的item的时候,不响应item的点击事件
            if (isActionViewShow || isDownToNormal || isUPToNormal) {
    
                isDownToNormal = false;
                isUPToNormal = false;
                if (isActionViewShow && openedIntemPosition != -1) {
    
                    turnToNormal();
                }
                return false;
            }
            return super.performItemClick(view, position, id);
        }
    
    
        /**
         * 隐藏操作view
         */
        public void turnToNormal() {
    
            if (mPointChild == null) {
    
                return;
            }
            isActionViewShow = false;
            ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mPointChild.getChildAt(0), "translationX", 0);
    
            ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(mPointChild.getChildAt(1),
                    "translationX", mActionViewWidth);
            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.playTogether(objectAnimator, objectAnimator1);
            animatorSet.setDuration(mAnimationTime);
            animatorSet.start();
            animatorSet.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
    
                    openedIntemPosition = -1;
    
                }
            });
    
        }
    
        /**
         * 显示操作view
         */
        private void show() {
    
            if (mPointChild == null) {
    
                return;
            }
    
            isActionViewShow = true;
            ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mPointChild.getChildAt(0), "translationX",
                    -mActionViewWidth);
    
            ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(mPointChild.getChildAt(1), "translationX",
                    -mActionViewWidth);
            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.playTogether(objectAnimator, objectAnimator1);
            animatorSet.setDuration(mAnimationTime);
            animatorSet.start();
            
        }
    
        /**
         * 是否显示
         * @return
         */
        public boolean isActionViewShow() {
            return isActionViewShow;
        }
    
    }
    

    这里面需要注意的是item的布局:

    <?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:background="@android:color/white"
        android:gravity="center_vertical"
        android:orientation="horizontal">
    
        <!--初显示界面-->
        <LinearLayout
            android:id="@+id/id_front"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/white"
            android:paddingBottom="10dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:paddingTop="10dp"
            android:orientation="horizontal">
    
            <ImageView
                android:id="@+id/infoImage"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:layout_centerVertical="true"
                android:scaleType="centerCrop"
                android:src="@android:drawable/star_on" />
    
            <LinearLayout
                android:layout_weight="3.0"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_centerVertical="true"
                android:layout_marginLeft="10dp"
                android:layout_toLeftOf="@+id/infoTimeAndCount"
                android:layout_toRightOf="@+id/infoImage"
                android:gravity="center_vertical"
                android:orientation="vertical">
    
                <TextView
                    android:id="@+id/infoTitle"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Jay" />
    
                <TextView
                    android:textSize="13sp"
                    android:id="@+id/infoLast"
                    android:textColor="@android:color/darker_gray"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="10dp"
                    android:text="什么事啊??" />
    
            </LinearLayout>
    
            <LinearLayout
                android:layout_weight="1.0"
                android:id="@+id/infoTimeAndCount"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:gravity="center_vertical|right"
                android:orientation="vertical">
    
                <TextView
                    android:id="@+id/infoTime"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Jay" />
    
                <TextView
    
                    android:id="@+id/infoCount"
                    android:textSize="13sp"
                    android:textColor="@android:color/white"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="10dp"
                    android:gravity="center"
                    android:text="99+"
    
                    />
    
            </LinearLayout>
        </LinearLayout>
    
        <!--滑动显示界面-->
        <LinearLayout
            android:id="@+id/id_back"
            android:layout_width="160dp"
            android:layout_height="70dp"
            android:background="@android:color/white"
            android:gravity="center|right"
            android:tag="id_back">
    
            <TextView
                android:id="@+id/id_putTop"
                android:textSize="19sp"
                android:textColor="@android:color/white"
                android:layout_width="80dp"
                android:layout_height="match_parent"
                android:background="@android:color/darker_gray"
                android:clickable="true"
                android:gravity="center"
                android:text="置顶" />
    
            <TextView
                android:id="@+id/id_delete"
                android:textSize="19sp"
                android:textColor="@android:color/white"
                android:layout_width="80dp"
                android:layout_height="match_parent"
                android:background="@color/red"
                android:clickable="true"
                android:gravity="center"
                android:text="删除" />
    
        </LinearLayout>
    
    </LinearLayout>
    

    以上就是关键代码了,大家可以直接拿来用,附上源码下载地址:~
    完美仿QQ消息界面功能

    程序员内功修炼手册 不定期分享程序员基础知识,大前端知识!想跟博主一块成长的快快关注吧!

    在这里插入图片描述

    展开全文
  • 学完了这阶段课程,学员将学会开发主流网站的前端效果,比如:焦点图、滚动展示图、网页防复制、网页自定义菜单、WebOS、美女时钟、无刷新评论、评分控件、表格特效、图片悬浮详细信息、微博界面、QQ消息框效果、Div...
  • 学完了这阶段课程,学员将学会开发主流网站的前端效果,比如:焦点图、滚动展示图、网页防复制、网页自定义菜单、WebOS、美女时钟、无刷新评论、评分控件、表格特效、图片悬浮详细信息、微博界面、QQ消息框效果、Div...
  • 亲测可用,需要安装微信PC版,我是付费了的一天下3000篇文章没有问题,没有付费的...我付过费,有啥懂的,可以问软件客服,具体方法就是点击页面最上方最右边的“登录软件”,出现的页面的底部有客服qq,微信等等。
  • 不管是 TCP还是 KCP计算 RTO时都有最小 RTO的限制,即便计算出来RTO为40ms,由于默认的 RTO是100ms,协议只有在100ms后才能检测到丢包,快速模式下为30ms,可以手动更改该值: kcp->rx_minrto = 10; 文档索引 ...
  • 自己在开发过程中收集的一些有用的干货现在全部分享出来,总的来说:个人的开发能力强,但更愿意借助巨人的肩膀 最全面的 Material Design 学习资料 博主每天有时间就在看的干货App:Gank.Io非官方客户端应用...
  • 今日校园每日自动提交疫情上报py脚本,支持邮件推送提交结果消息,支持几乎所有学校(今日校园) 使用了此脚本或者参考了这个项目,请自觉给项目点个star 本项目仅供学习交流使用,如作他用所承受的任何直接、间接...
  • 齐博V7 整站系统

    2013-09-25 11:35:21
    系统有在线充值功能,但是针对于没有网银的用户,你可以在后台使用点卡功能,生成一批点卡,然后打印出来销售,或者是把点卡密码赠送给用户实现会员金币充值功能。点卡面值与充值的金币个数及密码位数都是可以自由...
  • java源码包---java 源码 大量 实例

    千次下载 热门讨论 2013-04-18 23:15:26
     用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作方法及源代码 1个目标文件 摘要:Java源码,初学实例,波浪文字  Java波浪文字,一个利用...
  • java源码包2

    千次下载 热门讨论 2013-04-20 11:28:17
     用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作方法及源代码 1个目标文件 摘要:Java源码,初学实例,波浪文字  Java波浪文字,一个利用...
  • java源码包3

    千次下载 热门讨论 2013-04-20 11:30:13
     用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作方法及源代码 1个目标文件 摘要:Java源码,初学实例,波浪文字  Java波浪文字,一个利用...
  • 10、纠正在对FDD模式的磁盘执行文件恢复功能时,扫描后能立即显示恢复出来的分区的BUG。 11、纠正有时在FAT表损坏的情况下加载FAT分区时程序长时间停止响应的BUG。 12、纠正某些情况下搜索到NTFS分区的问题。 13...
  • Java编写的显示器显示模式检测程序 2个目标文件 内容索引:JAVA源码,系统相关,系统信息检测 用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作...
  • JAVA上百实例源码以及开源项目

    千次下载 热门讨论 2016-01-03 17:37:40
     用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作方法及源代码 1个目标文件 摘要:Java源码,初学实例,波浪文字  Java波浪文字,一个利用...
  • java源码包4

    千次下载 热门讨论 2013-04-20 11:31:44
     用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作方法及源代码 1个目标文件 摘要:Java源码,初学实例,波浪文字  Java波浪文字,一个利用...
  • Java编写的显示器显示模式检测程序 2个目标文件 内容索引:JAVA源码,系统相关,系统信息检测 用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作...
  • Java编写的显示器显示模式检测程序 2个目标文件 内容索引:JAVA源码,系统相关,系统信息检测 用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作...
  • vc++ 开发实例源码包

    2014-12-16 11:25:17
    代码里用了备份dll的方法,因此在自定义的函数中可以直接调用在内存中备份的dll代码,而需要再把函数头部改来改去。 IOCP反弹远控客户端模型,外加上线服务端,全部代码注释! 如题。这个是IOCP远程控制软件的...
  • 易语言 茶凉专用模块

    2010-05-04 12:26:36
    官方QQ群:92716369 ------------------------ -------------------------- ------------------------------ .版本 2 .子程序 按键, , 公开, 执行模拟按键(无返回值) .参数 键代码, 整数型, , 键代码 .参数 状态...
  • (注意:本资源为本人亲自总结,手工整理出来。共327个应用实例,文件较大共分为两卷 part1 和 part2 两部分,以下是详细目录) 一、J Query实例大全 1) AjaxJavaScript资源 1. JS+CSS仿腾讯QQ首页搜索框无刷新换肤...
  • (注意:本资源为本人亲自总结,手工整理出来。共327个应用实例,文件较大共分为两卷 part1 和 part2 两部分,以下是详细目录) 一、J Query实例大全 1) AjaxJavaScript资源 1. JS+CSS仿腾讯QQ首页搜索框无刷新换肤...
  • VueSocial something like QQ、weibo、weixin(仿微博、微信的聊天社交平台)前后端分离的vue+express+socket.io练手项目 前端代码在BlogPhone下,后端代码在server下。如果你觉得这个项目还不错的话,你的star是对...
  • DiskGenius4.5.0免费版

    2014-04-04 16:12:02
    10、纠正在对FDD模式的磁盘执行文件恢复功能时,扫描后能立即显示恢复出来的分区的BUG。 11、纠正有时在FAT表损坏的情况下加载FAT分区时程序长时间停止响应的BUG。 12、纠正某些情况下搜索到NTFS分区的问题。 13...
  • 用户以自己的ID为网址,每次为网站拉来一个流量,都会被系统记录,而给予相应的奖励,为了防止恶意刷新,同一IP在一段时间内的重复访问,将视为一次。(具体时间可在后台设置) 6、申请作家 为了给用户一个展示...
  • 另外可以使用concat从一个数组中复制一个副本出来。数组本身提供了很多方法让开发者使用来操作数组。 - length 数组的长度 - toString 可以返回一个以,拼接的字符串,相当于是调用了下join(','...
  • vc++ 应用源码包_1

    热门讨论 2012-09-15 14:22:12
    任务管理器应该大家都很熟悉,论坛里也有好多的任务管理器的源码,解决CListCtr刷新时滚动条跳到开始处。 VC++实现网络连接查看器源码 非常好的一个实例,把网络连接的UDP/TCP都插入到CList控件中显示出来。 VC++...
  • vc++ 应用源码包_2

    热门讨论 2012-09-15 14:27:40
    任务管理器应该大家都很熟悉,论坛里也有好多的任务管理器的源码,解决CListCtr刷新时滚动条跳到开始处。 VC++实现网络连接查看器源码 非常好的一个实例,把网络连接的UDP/TCP都插入到CList控件中显示出来。 VC++...
  • vc++ 应用源码包_6

    热门讨论 2012-09-15 14:59:46
    任务管理器应该大家都很熟悉,论坛里也有好多的任务管理器的源码,解决CListCtr刷新时滚动条跳到开始处。 VC++实现网络连接查看器源码 非常好的一个实例,把网络连接的UDP/TCP都插入到CList控件中显示出来。 VC++...

空空如也

空空如也

1 2 3
收藏数 47
精华内容 18
关键字:

qq刷新不出来消息