Android 仿QQ广告,Android 高仿QQ HD mini左右滑动菜单栏效果

Android 高仿QQ HD mini左右滑动菜单栏,动画逼真。首先来看看几张效果图:

1.进入程序时,首先显示中间菜单,即QQHD mini的最近会话列表。

3a1abf241adf77f2fd4a6a6256f0035f.png

2.向左滑动,或者点击左上角图标,可以展开左边菜单栏,即QQ HD mini的好友列表,有动画效果。

ec387b3ae72745939a3f12830f7df008.png

3.向右滑动或者点击右上角图标,可以展开右边菜单,即QQ HD mini的设置之类的布局,这里我放了一个自定义view,作为例子。

5ad6e5a8d68d123ba3bcfd9ce6d8781f.png

下面让我们来看看最重要的那个自定义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;

}

}

}

好了,高仿QQ HD mini左右滑动菜单栏效果 源码地址:

具体下载目录在 /2013年资料/5月/2日/高仿QQ HD mini左右滑动菜单栏效果

0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值