高仿QQ消息,可以下拉刷新带小红点

来源:互联网 发布:皮蓬生涯数据 编辑:程序博客网 时间:2024/06/10 09:34

最近在做即时通讯这一块,老板不知道怎么想的,反正完全是照着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消息界面功能

0 0
原创粉丝点击