【移动应用开发技术】怎么在Android中通过自定义ViewGroup实现淘宝商品详情页_第1页
【移动应用开发技术】怎么在Android中通过自定义ViewGroup实现淘宝商品详情页_第2页
【移动应用开发技术】怎么在Android中通过自定义ViewGroup实现淘宝商品详情页_第3页
【移动应用开发技术】怎么在Android中通过自定义ViewGroup实现淘宝商品详情页_第4页
【移动应用开发技术】怎么在Android中通过自定义ViewGroup实现淘宝商品详情页_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

【移动应用开发技术】怎么在Android中通过自定义ViewGroup实现淘宝商品详情页

这篇文章给大家介绍怎么在Android中通过自定义ViewGroup实现淘宝商品详情页,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。package

com.mcoy.snapscrollview;

import

android.content.Context;

import

android.util.AttributeSet;

import

android.util.Log;

import

android.view.MotionEvent;

import

android.view.VelocityTracker;

import

android.view.View;

import

android.view.ViewConfiguration;

import

android.view.ViewGroup;

import

android.widget.Scroller;

public

class

McoySnapPageLayout

extends

ViewGroup

{

。。。。

public

interface

McoySnapPage

{

/**

*

返回page根节点

*

*

@return

*/

View

getRootView();

/**

*

是否滑动到最顶端

*

第二页必须自己实现此方法,来判断是否已经滑动到第二页的顶部

*

并决定是否要继续滑动到第一页

*/

boolean

isAtTop();

/**

*

是否滑动到最底部

*

第一页必须自己实现此方法,来判断是否已经滑动到第二页的底部

*

并决定是否要继续滑动到第二页

*/

boolean

isAtBottom();

}

public

interface

PageSnapedListener

{

/**

*

@mcoy

*

当从某一页滑动到另一页完成时的回调函数

*/

void

onSnapedCompleted(int

derection);

}

。。。。。。

/**

*

设置上下页面

*

@param

pageTop

*

@param

pageBottom

*/

public

void

setSnapPages(McoySnapPage

pageTop,

McoySnapPage

pageBottom)

{

mPageTop

=

pageTop;

mPageBottom

=

pageBottom;

addPagesAndRefresh();

}

private

void

addPagesAndRefresh()

{

//

设置页面id

mPageTop.getRootView().setId(0);

mPageBottom.getRootView().setId(1);

addView(mPageTop.getRootView());

addView(mPageBottom.getRootView());

postInvalidate();

}

/**

*

@mcoy

add

*

computeScroll方法会调用postInvalidate()方法,

而postInvalidate()方法中系统

*

又会调用computeScroll方法,

因此会一直在循环互相调用,

循环的终结点是在computeScrollOffset()

*

当computeScrollOffset这个方法返回false时,说明已经结束滚动。

*

*

重要:真正的实现此view的滚动是调用scrollTo(mScroller.getCurrX(),

mScroller.getCurrY());

*/

@Override

public

void

computeScroll()

{

//先判断mScroller滚动是否完成

if

(mSputeScrollOffset())

{

if

(mScroller.getCurrY()

==

(mScroller.getFinalY()))

{

if

(mNextDataIndex

>

mDataIndex)

{

mFlipDrection

=

FLIP_DIRECTION_DOWN;

makePageToNext(mNextDataIndex);

}

else

if

(mNextDataIndex

<

mDataIndex)

{

mFlipDrection

=

FLIP_DIRECTION_UP;

makePageToPrev(mNextDataIndex);

}else{

mFlipDrection

=

FLIP_DIRECTION_CUR;

}

if(mPageSnapedListener

!=

null){

mPageSnapedListener.onSnapedCompleted(mFlipDrection);

}

}

//这里调用View的scrollTo()完成实际的滚动

scrollTo(mScroller.getCurrX(),

mScroller.getCurrY());

//必须调用该方法,否则不一定能看到滚动效果

postInvalidate();

}

}

private

void

makePageToNext(int

dataIndex)

{

mDataIndex

=

dataIndex;

mCurrentScreen

=

getCurrentScreen();

}

private

void

makePageToPrev(int

dataIndex)

{

mDataIndex

=

dataIndex;

mCurrentScreen

=

getCurrentScreen();

}

public

int

getCurrentScreen()

{

for

(int

i

=

0;

i

<

getChildCount();

i++)

{

if

(getChildAt(i).getId()

==

mDataIndex)

{

return

i;

}

}

return

mCurrentScreen;

}

public

View

getCurrentView()

{

for

(int

i

=

0;

i

<

getChildCount();

i++)

{

if

(getChildAt(i).getId()

==

mDataIndex)

{

return

getChildAt(i);

}

}

return

null;

}

/*

*

(non-Javadoc)

*

*

@see

*

android.view.ViewGroup#onInterceptTouchEvent(android.view.MotionEvent)

*

重写了父类的onInterceptTouchEvent(),主要功能是在onTouchEvent()方法之前处理

*

touch事件。包括:down、up、move事件。

*

当onInterceptTouchEvent()返回true时进入onTouchEvent()。

*/

@Override

public

boolean

onInterceptTouchEvent(MotionEvent

ev)

{

final

int

action

=

ev.getAction();

if

((action

==

MotionEvent.ACTION_MOVE)

&&

(mTouchState

!=

TOUCH_STATE_REST))

{

return

true;

}

final

float

x

=

ev.getX();

final

float

y

=

ev.getY();

switch

(action)

{

case

MotionEvent.ACTION_MOVE:

//

记录y与mLastMotionY差值的绝对值。

//

yDiff大于gapBetweenTopAndBottom时就认为界面拖动了足够大的距离,屏幕就可以移动了。

final

int

yDiff

=

(int)(y

-

mLastMotionY);

boolean

yMoved

=

Math.abs(yDiff)

>

gapBetweenTopAndBottom;

if

(yMoved)

{

if(MCOY_DEBUG)

{

Log.e(TAG,

"yDiff

is

"

+

yDiff);

Log.e(TAG,

"mPageTop.isFlipToBottom()

is

"

+

mPageTop.isAtBottom());

Log.e(TAG,

"mCurrentScreen

is

"

+

mCurrentScreen);

Log.e(TAG,

"mPageBottom.isFlipToTop()

is

"

+

mPageBottom.isAtTop());

}

if(yDiff

<

0

&&

mPageTop.isAtBottom()

&&

mCurrentScreen

==

0

||

yDiff

>

0

&&

mPageBottom.isAtTop()

&&

mCurrentScreen

==

1){

Log.e("mcoy",

"121212121212121212121212");

mTouchState

=

TOUCH_STATE_SCROLLING;

}

}

break;

case

MotionEvent.ACTION_DOWN:

//

Remember

location

of

down

touch

mLastMotionY

=

y;

Log.e("mcoy",

"mScroller.isFinished()

is

"

+

mScroller.isFinished());

mTouchState

=

mScroller.isFinished()

?

TOUCH_STATE_REST

:

TOUCH_STATE_SCROLLING;

break;

case

MotionEvent.ACTION_CANCEL:

case

MotionEvent.ACTION_UP:

//

Release

the

drag

mTouchState

=

TOUCH_STATE_REST;

break;

}

boolean

intercept

=

mTouchState

!=

TOUCH_STATE_REST;

Log.e("mcoy",

"McoySnapPageLayoutonInterceptTouchEvent

return

"

+

intercept);

return

intercept;

}

/*

*

(non-Javadoc)

*

*

@see

android.view.View#onTouchEvent(android.view.MotionEvent)

*

主要功能是处理onInterceptTouchEvent()返回值为true时传递过来的touch事件

*/

@Override

public

boolean

onTouchEvent(MotionEvent

ev)

{

Log.e("mcoy",

"onTouchEvent--"

+

System.currentTimeMillis());

if

(mVelocityTracker

==

null)

{

mVelocityTracker

=

VelocityTracker.obtain();

}

mVelocityTracker.addMovement(ev);

final

int

action

=

ev.getAction();

final

float

x

=

ev.getX();

final

float

y

=

ev.getY();

switch

(action)

{

case

MotionEvent.ACTION_DOWN:

if

(!mScroller.isFinished())

{

mScroller.abortAnimation();

}

break;

case

MotionEvent.ACTION_MOVE:

if(mTouchState

!=

TOUCH_STATE_SCROLLING){

//

记录y与mLastMotionY差值的绝对值。

//

yDiff大于gapBetweenTopAndBottom时就认为界面拖动了足够大的距离,屏幕就可以移动了。

final

int

yDiff

=

(int)

Math.abs(y

-

mLastMotionY);

boolean

yMoved

=

yDiff

>

gapBetweenTopAndBottom;

if

(yMoved)

{

mTouchState

=

TOUCH_STATE_SCROLLING;

}

}

//

手指拖动屏幕的处理

if

((mTouchState

==

TOUCH_STATE_SCROLLING))

{

//

Scroll

to

follow

the

motion

event

final

int

deltaY

=

(int)

(mLastMotionY

-

y);

mLastMotionY

=

y;

final

int

scrollY

=

getScrollY();

if(mCurrentScreen

==

0){//显示第一页,只能上拉时使用

if(mPageTop

!=

null

&&

mPageTop.isAtBottom()){

scrollBy(0,

Math.max(-1

*

scrollY,

deltaY));

}

}else{

if(mPageBottom

!=

null

&&

mPageBottom.isAtTop()){

scrollBy(0,

deltaY);

}

}

}

break;

case

MotionEvent.ACTION_CANCEL:

case

MotionEvent.ACTION_UP:

//

弹起手指后,切换屏幕的处理

if

(mTouchState

==

TOUCH_STATE_SCROLLING)

{

final

VelocityTracker

velocityTracker

=

mVelocityTracker;

velocityTputeCurrentVelocity(1000,

mMaximumVelocity);

int

velocityY

=

(int)

velocityTracker.getYVelocity();

if

(Math.abs(velocityY)

>

SNAP_VELOCITY)

{

if(

velocityY

>

0

&&

mCurrentScreen

==

1

&&

mPageBottom.isAtTop()){

snapToScreen(mDataIndex-1);

}else

if(velocityY

<

0

&&

mCurrentScreen

==

0){

snapToScreen(mDataIndex+1);

}else{

snapToScreen(mDataIndex);

}

}

else

{

snapToDestination();

}

if

(mVelocityTracker

!=

null)

{

mVelocityTracker.recycle();

mVelocityTracker

=

null;

}

}else{

}

mTouchState

=

TOUCH_STATE_REST;

break;

default:

break;

}

return

true;

}

private

void

clearOnTouchEvents(){

mTouchState

=

TOUCH_STATE_REST;

if

(mVelocityTracker

!=

null)

{

mVelocityTracker.recycle();

mVelocityTracker

=

null;

}

}

private

void

snapToDestination()

{

//

计算应该去哪个屏

final

int

flipHeight

=

getHeight()

/

8;

int

whichScreen

=

-1;

final

int

topEdge

=

getCurrentView().getTop();

if(topEdge

<

getScrollY()

&&

(getScrollY()-topEdge)

>=

flipHeight

&&

mCurrentScreen

==

0){

//向下滑动

whichScreen

=

mDataIndex

+

1;

}else

if(topEdge

>

getScrollY()

&&

(topEdge

-

getScrollY())

>=

flipHeight

&&

mCurrentScreen

==

1){

//向上滑动

whichScreen

=

mDataIndex

-

1;

}else{

whichScreen

=

mDataIndex;

}

Log.e(TAG,

"snapToDestination

mDataIndex

=

"

+

mDataIndex);

Log.e(TAG,

"snapToDestination

whichScreen

=

"

+

whichScreen);

snapToScreen(whichScreen);

}

private

void

snapToScreen(int

dataIndex)

{

if

(!mScroller.isFinished())

return;

final

int

direction

=

dataIndex

-

mDataIndex;

mNextDataIndex

=

dataIndex;

boolean

changingScreens

=

dataIndex

!=

mDataIndex;

View

focusedChild

=

getFocusedChild();

if

(focusedChild

!=

null

&&

changingScreens)

{

focusedChild.clearFocus();

}

//在这里判断是否已到目标位置~

int

newY

=

0;

switch

(direction)

{

case

1:

//需要滑动到第二页

Log.e(TAG,

"the

direction

is

1");

newY

=

getCurrentView().getBottom();

//

最终停留的位置

break;

case

-1:

//需要滑动到第一页

Log.e(TAG,

"the

direction

is

-1");

Log.e(TAG,

"getCurrentView().getTop()

is

"

+

getCurrentView().getTop()

+

"

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论