菜单栏设置高仿QQHD mini左右滑动菜单栏效果Strut2教程-java教程
本文纯属个人见解,是对前面学习的总结,如有描述不正确的地方还请高手指正~
首先来看看几张果效图:
1.进入程序时,首先表现间中菜单,即QQHD mini的近来话会列表。
2.向左滑动,或者点击左上角标图,可以开展边左菜单栏,即QQHD mini的友好列表,有动画果效。
3.向右滑动或者点击右上角标图,可以开展边右菜单,即QQHD mini的设置之类的布局,这里我放了一个自定义view,作为例子。
上面让我们来看看最主要的那个自定义view的码源:
/**
* 可阁下切换菜单栏的LinearLayout
*
* @author way
*
*/
public class CenterLayout extends LinearLayout {
private final static String TAG = "CenterLayout";
public static final int LEFT = 0x001;// 前当表现左菜单栏
public static final int RIGHT = 0x002;// 前当表现右菜单栏
public static final int MIDDLE = 0x000;// 前当表现间中主界面
private int mCurState = MIDDLE;// 前当表现的view
public final int MENU_border_Width = 50;// 边栏宽度
private Scroller mScroller;
private LinearLayout leftLayout, rightLayout, childLayout;
private Context context;
private boolean fling;
private boolean mIsBeingDragged = false;
private int mTouchSlop;
/**
* Position of the last motion event.
*/
private float mLastMotionX, mLastMotionY;
/**
* ID of the active pointer. This is used to retain consistency during
* drags/flings if multiple pointers are used.
*/
private int mActivePointerId = INVALID_POINTER;
/**
* Sentinel value for no current active pointer. Used by
* {@link #mActivePointerId}.
*/
private static final int INVALID_POINTER = -1;
int menuWidth = 0;
int moveWidth = 0;
// 3个构造器
public CenterLayout(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public CenterLayout(Context context) {
super(context);
initView(context);
}
public Scroller getScroller() {
return mScroller;
}
// 初始化view
public void initView(Context context) {
this.context = context;
this.menuWidth = MENU_border_Width;
this.mScroller = new Scroller(context, AnimationUtils.loadInterpolator(
context, android.R.anim.overshoot_interpolator));
final ViewConfiguration configuration = ViewConfiguration.get(context);
mTouchSlop = configuration.getScaledTouchSlop();
mCurState = MIDDLE;// 初始化认默状态
}
/**
* 取获屏幕宽度
*
* @param context
* @return
*/
private int getViewWidthInPix(Context context) {
int viewWidthInPix = -1;
if (viewWidthInPix == -1) {
WindowManager manager = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
viewWidthInPix = manager.getDefaultDisplay().getWidth();
}
return viewWidthInPix;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
super.onLayout(changed, left, top, right, bottom);
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.layout(child.getLeft() + moveWidth, child.getTop(),
child.getRight() + moveWidth, child.getBottom());
}
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), 0);
postInvalidate();
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
// Log.i(TAG, "onInterceptTouchEvent------>" + ev.getAction());
final int action = ev.getAction();
if ((action == MotionEvent.ACTION_MOVE) && (mIsBeingDragged)) {
return true;// 截拦不传递给child view
}
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
final float x = ev.getX();
final float y = ev.getY();
if (!inChild((int) x, (int) y)) {
mIsBeingDragged = false;
break;
// 超越边界,return false传递给子view处置
}
/*
* Remember location of down touch. ACTION_DOWN always refers to
* pointer index 0.
*/
mLastMotionX = x;
mLastMotionY = y;
mActivePointerId = ev.getPointerId(0);
/*
* If being flinged and user touches the screen, initiate drag;
* otherwise don't. mScroller.isFinished should be false when being
* flinged.
*/
mIsBeingDragged = !mScroller.isFinished();
break;
}
case MotionEvent.ACTION_MOVE: {
/*
* mIsBeingDragged == false, otherwise the shortcut would have
* caught it. Check whether the user has moved far enough from his
* original down touch.
*/
/*
* Locally do absolute value. mLastMotionY is set to the y value of
* the down event.
*/
final int activePointerId = mActivePointerId;
if (activePointerId == INVALID_POINTER) {
// If we don't have a valid id, the touch down wasn't on
// content.
break;
}
final int pointerIndex = ev.findPointerIndex(activePointerId);
final float x = ev.getX(pointerIndex);
final float y = ev.getY(pointerIndex);
final int xDiff = (int) Math.abs(x - mLastMotionX);
final int yDiff = (int) Math.abs(y - mLastMotionY);
if (xDiff > mTouchSlop && yDiff < xDiff) {
mIsBeingDragged = true;
}
break;
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
mIsBeingDragged = false;
mActivePointerId = INVALID_POINTER;
scrollToScreen();
break;
}
return mIsBeingDragged;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// Log.i(TAG, "onTouchEvent ---->>>>>" + event.getAction());
if (event.getAction() == MotionEvent.ACTION_DOWN
&& !inChild((int) event.getX(), (int) event.getY())) {
// Don't handle edge touches immediately -- they may actually belong
// to one of our
// descendants.
return false;
}
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
return true; // 本VIEW消化失落
case MotionEvent.ACTION_MOVE:
final int activePointerIndex = event
.findPointerIndex(mActivePointerId);
final float x = event.getX(activePointerIndex);
final float y = event.getY(activePointerIndex);
final int distanceX = (int) /* Math.abs */-(x - mLastMotionX);
// 在滑动中程过,就需要表现新的brotherView,不然表现的还是之前的brotherView,最后松开手时会然突变称新brotherView,影响休会
if (distanceX < 0 && getScrollX() < 0 && leftLayout != null) {
setBrotherVisibility(LEFT);
} else if (distanceX > 0 && getScrollX() > 0 && rightLayout != null) {
setBrotherVisibility(RIGHT);
} else {
setBrotherVisibility(MIDDLE);
}
scrollBy((int) distanceX, 0);
mLastMotionX = x;
mLastMotionY = y;
break;
case MotionEvent.ACTION_UP:
mIsBeingDragged = false;
mActivePointerId = INVALID_POINTER;
scrollToScreen();
break;
default:
return super.onTouchEvent(event);
}
return mIsBeingDragged;
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
// TODO Auto-generated method stub
super.onScrollChanged(l, t, oldl, oldt);
}
private void scrollToScreen() {
int scrollDistance = 0;
if (Math.abs(getScrollX()) > getWidth() / 2)
scrollDistance = (getScrollX() > 0) ? getWidth() - menuWidth
- getScrollX() : -(getWidth() - menuWidth - Math
.abs(getScrollX()));
else
scrollDistance = -getScrollX();
int distance = scrollDistance + getScrollX();
Log.i(TAG, " distance = " + distance);
if (distance > 0) {
mCurState = RIGHT;
} else if (distance < 0) {
mCurState = LEFT;
} else {
mCurState = MIDDLE;
}
mScroller.startScroll(getScrollX(), 0, scrollDistance, 0,
Math.abs(scrollDistance) * 2);
invalidate();
}
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
if (Math.abs(velocityX) > ViewConfiguration.get(context)
.getScaledMinimumFlingVelocity()) {
fling = true;
scrollToScreen();
}
return fling;
}
private boolean inChild(int x, int y) {
if (getChildCount() > 0) {
final int scrollX = mScroller.getCurrX();
final View child = getChildAt(0);
return !(scrollX + x < 0 || scrollX + x > getWidth() || y < 0 || y > getHeight());
}
return false;
}
/**
* 设置前当表现的view
*
* @param whichpg
*/
public void setPage(int whichpg) {
int targetX = 0, moveDistance = 0;
if (whichpg == LEFT) {
targetX = -(getViewWidthInPix(context) - menuWidth);
mCurState = LEFT;
} else if (whichpg == RIGHT) {
targetX = getViewWidthInPix(context) - menuWidth;
mCurState = RIGHT;
} else {
mCurState = MIDDLE;
}
setBrotherVisibility(whichpg);
moveDistance = targetX - getScrollX();
mScroller.startScroll(getScrollX(), 0, moveDistance, 0,
Math.abs(moveDistance) * 2);
invalidate();
}
/**
* 返回前当表现的view
*
* @return
*/
public int getPage() {
return mCurState;
}
public void addChildView(View child) {
this.childLayout.addView(child);
}
/**
* 设置BrotherView
*
* @param left
* @param right
*/
public void setBrotherLayout(LinearLayout left, LinearLayout right) {
this.leftLayout = left;
this.rightLayout = right;
}
/**
* 根据前当状态表现或隐藏view
*
* @param state
*/
private void setBrotherVisibility(int state) {
switch (state) {
case LEFT:
rightLayout.setVisibility(View.GONE);
leftLayout.setVisibility(View.VISIBLE);
break;
case RIGHT:
rightLayout.setVisibility(View.VISIBLE);
leftLayout.setVisibility(View.GONE);
break;
case MIDDLE:
break;
default:
break;
}
}
}
好了,稍后为大家贴出整完的码源。
文章结束给大家分享下程序员的一些笑话语录:
程序员喝酒
我偶尔采用“木马策略”、“交叉测试”,时间不长就开始“频繁分配释放资源”,“cache”也是免不了的了,
不过我从不搞“轮巡”,也不会“捕获异常”,更不会“程序异常”,因为我有理性
克制的。

浙公网安备 33010602011771号