您的位置:首页 > 移动开发 > Android开发

Android 高仿 QQ5.2 侧滑菜单效果及QQmini效果

2014-12-05 21:16 471 查看


参考了:Android的高仿QQ5.0侧滑菜单效果自定义控件来袭


然后自己撰写了QQ5.2效果,并且可以切换QQmini效果,个人话语不多,见谅!

本人已经开源到了TaoCode,可以使用SVN免费更新下载:
http://code.taobao.org/svn/imitateqqandqqmini/trunk
本人TaoCode首页

CSDN:点击下载
qq5.0效果:



qq5.2效果:



qqmini效果:






首先看下布局:


<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/ic_launcher" >

    <com.bluemor.reddotface.view.DragLayout
        android:id="@+id/dl"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <FrameLayout
            android:id="@+id/flBack"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >

            <ListView
                android:id="@+id/lv"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:cacheColorHint="#00000000"
                android:divider="@null"
                android:scrollbarSize="0dp"
                android:scrollbars="@null" />
        </FrameLayout>

        <com.bluemor.reddotface.view.MyFrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#eeeeee" >

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent" >

                <RelativeLayout
                    android:id="@+id/rl_title"
                    android:layout_width="match_parent"
                    android:layout_height="55dp"
                    android:background="#3683C1" >

                    <ImageView
                        android:id="@+id/iv_icon"
                        android:layout_width="42dp"
                        android:layout_height="42dp"
                        android:layout_centerVertical="true"
                        android:layout_marginLeft="10dp"
                        android:scaleType="centerCrop"
                        android:src="@drawable/ic_launcher" />

                    <Button
                        android:id="@+id/btn"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_centerInParent="true"
                        android:text="@string/app_name"
                        android:textColor="#ffffff"
                        android:textSize="20sp" />
                </RelativeLayout>

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_below="@id/rl_title"
                    android:text="@string/text" />
            </RelativeLayout>
        </com.bluemor.reddotface.view.MyFrameLayout>
    </com.bluemor.reddotface.view.DragLayout>
</FrameLayout>




然后,子布局(前面的显示的):


package com.bluemor.reddotface.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.FrameLayout;

import com.bluemor.reddotface.view.DragLayout.Status;

/**
* @author chenyingyou
* @see http://blog.csdn.net/chenlove1 */
public class MyFrameLayout extends FrameLayout {
private DragLayout dl;

public MyFrameLayout(Context context) {
super(context);
}

public MyFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}

public MyFrameLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}

public void setDragLayout(DragLayout dl) {
this.dl = dl;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (dl.getStatus() != Status.Close) {
return true;
}
return super.onInterceptTouchEvent(event);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
if (dl.getStatus() != Status.Close) {
if (event.getAction() == MotionEvent.ACTION_UP) {
dl.close();
}
return true;
}
return super.onTouchEvent(event);
}

}





最后,父布局(后面的布局):


package com.bluemor.reddotface.view;

import android.content.Context;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;

import com.bluemor.reddotface.R;
import com.nineoldandroids.view.ViewHelper;

/**
* @author chenyingyou
* @see http://blog.csdn.net/chenlove1 */
public class DragLayout extends FrameLayout {

private boolean isShowShadow = true;
private boolean isQQEffect = true;

private GestureDetectorCompat gestureDetector;// 拦截手势判断
private ViewDragHelper dragHelper;// 拦截后的手势监听
private DragListener dragListener;// 外界回调

private int rangeLeft;// 左边的拉开宽度
private int rangeRight;// 右边的拉开宽度
private final float ratioLeft = 0.5f;// 左边的拉开系数
private final float ratioRight = 0.25f;// 右边的拉开系数
private int width;// 宽度
private int height;// 高度
private int shifting;// shifting偏移量(正数为左边偏移量,负数为右边偏移量)

private ImageView ivshadow;
private FrameLayout flBackground;
private MyFrameLayout flMain;

private Status status = Status.Close;

public enum Status {
Drag, OpenLeft, OpenRight, Close
}

public DragLayout(Context context) {
this(context, null);
}

public DragLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public DragLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
gestureDetector = new GestureDetectorCompat(context,
new YScrollDetector());
dragHelper = ViewDragHelper.create(this, dragHelperCallback);
}

class YScrollDetector extends SimpleOnGestureListener {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float dx,
float dy) {
return Math.abs(dy) <= Math.abs(dx);
}
}

// 拦截后的手势监听回调
private ViewDragHelper.Callback dragHelperCallback = new ViewDragHelper.Callback() {

@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
if (shifting + dx < rangeRight) {// 向左拉
return rangeRight;
} else if (shifting + dx > rangeLeft) {// 向右拉
return rangeLeft;
} else {
return left;
}
}

@Override
public boolean tryCaptureView(View child, int pointerId) {
return true;
}

@Override
public int getViewHorizontalDragRange(View child) {
return width;
}

@Override
// 当手势触发到抬起动作
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);

if (shifting > 0) {
if (xvel > 0) {// 最后向右滑
openLeft();
} else if (xvel < 0) {// 最后向左滑
close();
} else if (releasedChild == flMain
&& shifting > rangeLeft * 0.3) {
openLeft();
} else if (releasedChild == flBackground
&& shifting > rangeLeft * 0.7) {
openLeft();
} else {
close();
}
} else {
if (xvel > 0) {
close();
} else if (xvel < 0) {
openRight();
} else if (releasedChild == flMain
&& shifting > rangeRight * 0.3) {
close();
} else if (releasedChild == flBackground
&& shifting > rangeRight * 0.7) {
close();
} else {
close();
}
}

}

@Override
// 当手势触发到了某个changedView回调这方法
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
if (changedView == flMain) {
shifting = left;
} else {
shifting = shifting + left;
}

if (shifting < rangeRight) {
shifting = rangeRight;
} else if (shifting > rangeLeft) {
shifting = rangeLeft;
}

if (isShowShadow) {
ivshadow.layout(shifting, 0, shifting + width, height);
}

if (changedView == flBackground) {
flMain.layout(shifting, 0, shifting + width, height);
flBackground.layout(0, 0, width, height);
}

dispatchDragEvent(shifting);
}
};

private void dispatchDragEvent(int shifting) {
float percent;
boolean isLeft;

if (shifting < 0) {
isLeft = false;
percent = shifting / (float) rangeRight;
} else {
isLeft = true;
percent = shifting / (float) rangeLeft;
}

if (dragListener != null) {
dragListener.onDrag(percent, isLeft);
Status lastStatus = status;
if (lastStatus != getStatus() && status == Status.Close) {
dragListener.onClose();
} else if (lastStatus != getStatus() && status == Status.OpenLeft) {
dragListener.openLeft();
} else if (lastStatus != getStatus() && status == Status.OpenRight) {
dragListener.openRight();
}
}

if (!isQQEffect) {
setBackgroundColor(evaluate(percent, 0x77777777, 0));
return;
}

float f1 = 1 - percent * 0.2f;
ViewHelper.setScaleX(flMain, f1);
ViewHelper.setScaleY(flMain, f1);

float translationX;
float ratioX = 1.8f;
if (isLeft) {
translationX = -flBackground.getWidth() / ratioX
+ flBackground.getWidth() / ratioX * percent;
} else {
translationX = flBackground.getWidth() / ratioX
- flBackground.getWidth() / ratioX * percent;
}
ViewHelper.setTranslationX(flBackground, translationX);
ViewHelper.setScaleX(flBackground, 0.5f + 0.5f * percent);
ViewHelper.setScaleY(flBackground, 0.5f + 0.5f * percent);
ViewHelper.setAlpha(flBackground, percent);
if (isShowShadow) {
ViewHelper.setScaleX(ivshadow, f1 * 1.8f * (1 - percent * 0.12f));
ViewHelper.setScaleY(ivshadow, f1 * 1.8f * (1 - percent * 0.12f));
}
setBackgroundColor(evaluate(percent, 0xDD000000, 0));

}

private static Integer evaluate(float fraction, Integer startValue,
Integer endValue) {
int startInt = startValue;
int startA = (startInt >> 24) & 0xff;
int startR = (startInt >> 16) & 0xff;
int startG = (startInt >> 8) & 0xff;
int startB = startInt & 0xff;
int endInt = (Integer) endValue;
int endA = (endInt >> 24) & 0xff;
int endR = (endInt >> 16) & 0xff;
int endG = (endInt >> 8) & 0xff;
int endB = endInt & 0xff;
return (int) ((startA + (int) (fraction * (endA - startA))) << 24)
| (int) ((startR + (int) (fraction * (endR - startR))) << 16)
| (int) ((startG + (int) (fraction * (endG - startG))) << 8)
| (int) ((startB + (int) (fraction * (endB - startB))));
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return dragHelper.shouldInterceptTouchEvent(ev)
&& gestureDetector.onTouchEvent(ev);
}

@Override
public boolean onTouchEvent(MotionEvent e) {
try {
dragHelper.processTouchEvent(e);
} catch (Exception ex) {
ex.printStackTrace();
}
return false;
}

@Override
// 加载完成xml后,就会执行那个方法
protected void onFinishInflate() {
super.onFinishInflate();
if (isShowShadow) {
ivshadow = new ImageView(getContext());
ivshadow.setImageResource(R.drawable.shadow);
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
addView(ivshadow, 1, lp);
}
flBackground = (FrameLayout) getChildAt(0);
flMain = (MyFrameLayout) getChildAt(isShowShadow ? 2 : 1);
flMain.setDragLayout(this);
flBackground.setClickable(true);
flMain.setClickable(true);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = flBackground.getMeasuredWidth();
height = flBackground.getMeasuredHeight();
rangeLeft = (int) (width * ratioLeft);
rangeRight = -(int) (width * ratioRight);
}

@Override
public void computeScroll() {
if (dragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}

public Status getStatus() {
if (shifting == 0) {
status = Status.Close;
} else if (shifting == rangeLeft) {
status = Status.OpenLeft;
} else if (shifting == rangeRight) {
status = Status.OpenRight;
} else {
status = Status.Drag;
}
return status;
}

public void openLeft() {
openLeft(true);
}

public void openLeft(boolean animate) {
if (animate) {
if (dragHelper.smoothSlideViewTo(flMain, rangeLeft, 0)) {
ViewCompat.postInvalidateOnAnimation(this);
}
} else {
flMain.layout(rangeLeft, 0, rangeLeft * 2, height);
dispatchDragEvent(rangeLeft);
}
}

public void openRight() {
openRight(true);
}

public void openRight(boolean animate) {
if (animate) {
if (dragHelper.smoothSlideViewTo(flMain, rangeRight, 0)) {
ViewCompat.postInvalidateOnAnimation(this);
}
} else {
flMain.layout(rangeRight, 0, rangeRight * 2, height);
dispatchDragEvent(rangeRight);
}
}

public void close() {
close(true);
}

public void close(boolean animate) {
if (animate) {
if (dragHelper.smoothSlideViewTo(flMain, 0, 0)) {
ViewCompat.postInvalidateOnAnimation(this);
}
} else {
flMain.layout(0, 0, width, height);
dispatchDragEvent(0);
}
}

/** 设置是否要QQ效果 */
public void setIsQQEffect(boolean isQQEffect) {
this.isQQEffect = isQQEffect;
if (!isQQEffect) {
ViewHelper.setTranslationX(flBackground, 0);
ViewHelper.setScaleX(flBackground, 1);
ViewHelper.setScaleY(flBackground, 1);
ViewHelper.setAlpha(flBackground, 1);
}
}

public boolean isQQEffect() {
return isQQEffect;
}

/** 不需要右边侧滑 */
public void setNotUsedRight() {
rangeRight = 0;
}

/** 不需要左边侧滑 */
public void setNotUsedLeft() {
rangeRight = 0;
}

public void setDragListener(DragListener dragListener) {
this.dragListener = dragListener;
}

}




内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: