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

安卓侧边 4000 栏实现

2016-06-01 15:31 369 查看

安卓侧滑布局实现

来,先上效果图



package xiaolin.widget;

import android.content.Context;;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;

import xiaolin.utils.Utils;

/**
* 只有平移效果的侧边栏
* Created by XiaoLin on 2016/1/14.
*/
public class ATranslationLayout extends ViewGroup {

public static final String TAG = "ATranslationLayout";
private static final int MININERCEPTXVILOCITY = 8;   // 最小拦截速度(dp)
private static final int MINTOUCHVILOCITY = 300;     // 最小触发速度(dp)
private static final float drawerTime = 2.5f;       // 动画时间

private Scroller mScroller = null;
private VelocityTracker mVelocity = null;
private OnTranslationListener mOnTranslationListener = null;

private boolean isTouchRight = false;
private boolean isBeingDragged = false;
private boolean isUnableToDragged = false;
private PointF mLastInterceptPointF = new PointF();
private float mLastTouchX = 0;
private float mFirstTouchX = 0;

protected int menuWidth = 0;                    // 菜单宽度
protected boolean mIsOpenMenu = false;       // 是否显示菜单
protected boolean isDraggedToRight = false;            // 是否向右边移动

public ATranslationLayout(Context context) {
super(context);
init();
}

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

public ATranslationLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}

private void init() {
mScroller = new Scroller(getContext());
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
menuWidth = (int) (width * 0.75f);         // 菜单宽度
int childCount = getChildCount();
if (childCount == 0) {
return;
}
View menuView = getChildAt(0);
// 合成菜单的测量宽度
int menuWidthSpec = MeasureSpec.makeMeasureSpec(menuWidth, MeasureSpec.EXACTLY);
int menuheightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
menuView.measure(menuWidthSpec, menuheightSpec);
for (int i = 1; i < childCount; i++) {
View childView1 = getChildAt(i);
childView1.measure(widthMeasureSpec, heightMeasureSpec);
}
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int childCount = getChildCount();
if (childCount == 0) {
return;
}
View menuView = getChildAt(0);
// 设置子视图的位置,左上角坐标,宽高
menuView.layout(-menuView.getMeasuredWidth(), 0, 0, menuView.getMeasuredHeight());

int left = 0;
for (int i = 1; i < childCount; i++) {
View childView = getChildAt(i);
int w = childView.getMeasuredWidth();
childView.layout(left, 0, left + w, childView.getMeasuredHeight());
left += w;
}
}

@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
int x = mScroller.getCurrX();
scrollTo(x, 0);
// 调用invalidate()无效
postInvalidate();
if (mOnTranslationListener != null) {
mOnTranslationListener.progress(isDraggedToRight, -x / (float)menuWidth);
}
}
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
int action = event.getAction();
PointF pointF = new PointF(event.getX(), event.getY());
if (action != 0) {
if (isBeingDragged) {
return true;
}
if (isUnableToDragged) {
return false;
}
}
if (action == MotionEvent.ACTION_DOWN) {
mLastInterceptPointF.set(pointF);
isBeingDragged = false;
isUnableToDragged = false;
if(mScroller.isFinished()){
isDraggedToRight = !isOpenMenu();
}
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
return true;
} else if (mIsOpenMenu) {
if (event.getX() > menuWidth) {
isBeingDragged = true;
}
}
} else if (action == MotionEvent.ACTION_MOVE) {
float dx = Math.abs(pointF.x - mLastInterceptPointF.x);
float dy = Math.abs(pointF.y - mLastInterceptPointF.y);
if (dy > dx) {  // 上下滑动
isUnableToDragged = true;
} else if (pointF.x < mLastInterceptPointF.x && !mIsOpenMenu) { // 往左滑动&&已关窗
isUnableToDragged = true;
} else if (pointF.x > mLastInterceptPointF.y && mIsOpenMenu) {    // 往右滑动&&已开窗
isUnableToDragged = true;
} else if (dx > dy && dx > Utils.dpToPx(MININERCEPTXVILOCITY, getResources())) {  // 往右并且大于一定速度
isBeingDragged = true;
}
mLastInterceptPointF.x = pointF.x;
mLastInterceptPointF.y = pointF.y;
}
return isBeingDragged;
}

// 触摸事件
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
float x = event.getX();
if (mVelocity == null) {
mVelocity = VelocityTracker.obtain();
mLastTouchX = x;
if (mIsOpenMenu && x > menuWidth) {
isTouchRight = true;
mFirstTouchX = x;
} else {
isTouchRight = false;
}
}
mVelocity.addMovement(event);
if (action == MotionEvent.ACTION_DOWN) {// 可能无此动作

} else if (action == MotionEvent.ACTION_MOVE) { // 正在滑动
float dx = x - mLastTouchX;
drawerViewBy((int) dx);
mLastTouchX = x;
} else if (action == MotionEvent.ACTION_UP) {
if (isTouchRight && mFirstTouchX == x) {
openMenu(false);
mVelocity.recycle();
mVelocity = null;
return true;
} else {
mVelocity.computeCurrentVelocity(1000);

c5c9
if (mVelocity.getXVelocity() < -Utils.dpToPx(MINTOUCHVILOCITY, getResources())) {
openMenu(false);
} else if (mVelocity.getXVelocity() > Utils.dpToPx(MININERCEPTXVILOCITY, getResources())) {
openMenu(true);
} else {
if (-getScrollX() > menuWidth / 2) {
openMenu(true);
} else {
openMenu(false);
}
}
mVelocity.recycle();
mVelocity = null;
}
}
return true;
}

// 按键监听
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
int code = event.getKeyCode();
int action = event.getAction();
if (code == KeyEvent.KEYCODE_BACK && action == KeyEvent.ACTION_UP) {
if (mIsOpenMenu) {
openMenu(false);
return true;
}
}
return super.dispatchKeyEvent(event);
}

// 滚动距离并判断范围
protected void drawerViewBy(int dx) {
dx = -dx;
int x = getScrollX();
if (x + dx > 0) {
scrollTo(0, 0);
} else if (x + dx < -menuWidth) {
scrollTo(-menuWidth, 0);
} else {
scrollTo(x + dx, 0);
}
if (mOnTranslationListener != null) {
mOnTranslationListener.progress(isDraggedToRight, -getScrollX() / (float) menuWidth);
}
}

public void openMenu(Boolean isOpen) {
mIsOpenMenu = isOpen;
int x = getScrollX();
if (isOpen) {
int time = (int) (Math.abs(-menuWidth - x) / Utils.dpToPx(1f, getResources()) * drawerTime);
mScroller.startScroll(x, 0, -menuWidth - x, 0, time);
if (x == 0) {
isDraggedToRight = true;
}
} else {
int time = (int) (Math.abs(x) / Utils.dpToPx(1f, getResources()) * drawerTime);
mScroller.startScroll(x, 0, -x, 0, time);
if (x == -menuWidth) {
isDraggedToRight = false;
}
}
if (mOnTranslationListener != null) {
mOnTranslationListener.fold(mIsOpenMenu);
}
postInvalidate();
}

// 是打开菜单
public boolean isOpenMenu() {
return mIsOpenMenu;
}

// 设置监听
public void setFoldingListener(OnTranslationListener listener) {
this.mOnTranslationListener = listener;
}

// 监听接口
public interface OnTranslationListener {
void fold(boolean isOpen);
void progress(boolean isToRight, float progress);// 0.0f-1.0f
}

}


package xiaolin.utils;

import android.content.res.Resources;
import android.util.TypedValue;

/**
* Created by Administrator on 2016/1/17.
*/
public class Utils {

/**
* dp转为像素
* @param dp
* @param resources
* @return
*/
public static float dpToPx(float dp, Resources resources){
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, resources.getDisplayMetrics());
}
}


然后只要在xml里使用就行了,里面放的是侧边的布局

<?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="#cacaca">

<xiaolin.widget.ATranslationLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@drawable/bg" />

</xiaolin.widget.ATranslationLayout>

</LinearLayout>


效果图在上面

如果里面添加两个布局的话就会变成这样

<?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="#cacaca">

<xiaolin.widget.ATranslationLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@drawable/bg" />

<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/img_bg"
android:scaleType="centerCrop"/>

</xiaolin.widget.ATranslationLayout>

</LinearLayout>




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