【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android怎么實(shí)現(xiàn)購(gòu)物車添加商品動(dòng)畫_第1頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android怎么實(shí)現(xiàn)購(gòu)物車添加商品動(dòng)畫_第2頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android怎么實(shí)現(xiàn)購(gòu)物車添加商品動(dòng)畫_第3頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android怎么實(shí)現(xiàn)購(gòu)物車添加商品動(dòng)畫_第4頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android怎么實(shí)現(xiàn)購(gòu)物車添加商品動(dòng)畫_第5頁(yè)
已閱讀5頁(yè),還剩4頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android怎么實(shí)現(xiàn)購(gòu)物車添加商品動(dòng)畫

這篇文章將為大家詳細(xì)講解有關(guān)Android怎么實(shí)現(xiàn)購(gòu)物車添加商品動(dòng)畫,在下覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。實(shí)現(xiàn)需求:在商品列表頁(yè)面,從列表Item添加商品的時(shí)候,需要一個(gè)動(dòng)畫,仿佛是是往購(gòu)物車?yán)锾砑由唐贰?shí)現(xiàn)思路:獲取起始點(diǎn)與終點(diǎn)的坐標(biāo),利用PathMeasure繪制貝塞爾曲線;為點(diǎn)擊的Item商品View設(shè)置屬性動(dòng)畫;監(jiān)聽(tīng)屬性動(dòng)畫的update,改變View的坐標(biāo);實(shí)現(xiàn)效果:實(shí)現(xiàn)中會(huì)用到PathMeasure類:我們主要使用它兩個(gè)方法:1、獲取長(zhǎng)度:/**

//獲取弧線的總長(zhǎng)度(周長(zhǎng))

*

Return

the

total

length

of

the

current

contour,

or

0

if

no

path

is

*

associated

with

this

measure

object.

*/

public

float

getLength()

{

return

native_getLength(native_instance);//系統(tǒng)調(diào)用native

方法;

}2、獲取坐標(biāo):/**

*

Pins

distance

to

0

<=

distance

<=

getLength(),

and

then

computes

the

*

corresponding

position

and

tangent.

Returns

false

if

there

is

no

path,

*

or

a

zero-length

path

was

specified,

in

which

case

position

and

tangent

*

are

unchanged.

*

*

@param

distance

The

distance

along

the

current

contour

to

sample

*

@param

pos

If

not

null,

eturns

the

sampled

position

(x==[0],

y==[1])

*

@param

tan

If

not

null,

returns

the

sampled

tangent

(x==[0],

y==[1])

*

@return

false

if

there

was

no

path

associated

with

this

measure

object

*/

public

boolean

getPosTan(float

distance,

float

pos[],

float

tan[])

{

if

(pos

!=

null

&&

pos.length

<

2

||

tan

!=

null

&&

tan.length

<

2)

{

throw

new

ArrayIndexOutOfBoundsException();

}

return

native_getPosTan(native_instance,

distance,

pos,

tan);

}方法getPosTan(floatdistance,floatpos[],floattan[])-path為null,返回falsedistance為一個(gè)0-getLength()之間的值,根據(jù)這個(gè)值PathMeasure會(huì)計(jì)算出當(dāng)前點(diǎn)的坐標(biāo)封裝到pos中。上面這句話我們可以這么來(lái)理解,不管實(shí)際Path多么的復(fù)雜,PathMeasure都相當(dāng)于做了一個(gè)事情,就是把Path“拉直”,然后給了我們一個(gè)接口(getLength)告訴我們path的總長(zhǎng)度,然后我們想要知道具體某一點(diǎn)的坐標(biāo),只需要用相對(duì)的distance去取即可,這樣就省去了自己用函數(shù)模擬path,然后計(jì)算獲取點(diǎn)坐標(biāo)的過(guò)程。代碼如下:public

class

GoodsListActivity

extends

AppCompatActivity

{

private

RelativeLayout

mRootRl;

private

RecyclerView

mGoodsRecyclerView;

private

ImageView

mCarImageView;

private

TextView

mCountTv;

private

List<Bitmap>

mBitmapList

=

new

ArrayList<>();

private

PathMeasure

mPathMeasure;

private

float[]

mCurrentPosition

=

new

float[2];

private

int

mCount

=

0;

@Override

protected

void

onCreate(Bundle

savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_goods_list);

initView();

initData();

GoodsAdapter

goodsAdapter

=

new

GoodsAdapter(mBitmapList);

mGoodsRecyclerView.setLayoutManager(new

LinearLayoutManager(this));

mGoodsRecyclerView.setAdapter(goodsAdapter);

}

private

void

initView(){

mGoodsRecyclerView

=

(RecyclerView)findViewById(R.id.recyclerView);

mCarImageView

=

(ImageView)findViewById(R.id.imageview_shop_car);

mCountTv

=

(TextView)findViewById(R.id.tv_count);

mRootRl

=

(RelativeLayout)findViewById(R.id.rl_root);

}

private

void

initData(){

mBitmapList.add(BitmapFactory.decodeResource(getResources(),

R.drawable.car));

mBitmapList.add(BitmapFactory.decodeResource(getResources(),

R.drawable.car));

mBitmapList.add(BitmapFactory.decodeResource(getResources(),

R.drawable.car));

}

class

GoodsAdapter

extends

RecyclerView.Adapter<GoodsViewHolder>{

private

List<Bitmap>

mData;

public

GoodsAdapter(List<Bitmap>

data)

{

mData

=

data;

}

@Override

public

GoodsViewHolder

onCreateViewHolder(ViewGroup

parent,

int

viewType)

{

View

itemView

=

LayoutInflater.from(GoodsListActivity.this)

.inflate(R.layout.rv_goods_item,

parent,

false);

return

new

GoodsViewHolder(itemView);

}

@Override

public

void

onBindViewHolder(final

GoodsViewHolder

holder,

int

position)

{

holder.ivGood.setImageBitmap(mData.get(position));

holder.tvBuy.setOnClickListener(new

View.OnClickListener()

{

@Override

public

void

onClick(View

v)

{

addGoodToCar(holder.ivGood);

}

});

}

@Override

public

int

getItemCount()

{

return

mData

!=

null

?

mData.size()

:

0;

}

}

private

void

addGoodToCar(ImageView

imageView){

final

ImageView

view

=

new

ImageView(GoodsListActivity.this);

view.setImageDrawable(imageView.getDrawable());

RelativeLayout.LayoutParams

layoutParams

=

new

RelativeLayout.LayoutParams(100,

100);

mRootRl.addView(view,

layoutParams);

//二、計(jì)算動(dòng)畫開(kāi)始/結(jié)束點(diǎn)的坐標(biāo)的準(zhǔn)備工作

//得到父布局的起始點(diǎn)坐標(biāo)(用于輔助計(jì)算動(dòng)畫開(kāi)始/結(jié)束時(shí)的點(diǎn)的坐標(biāo))

int[]

parentLoc

=

new

int[2];

mRootRl.getLocationInWindow(parentLoc);

//得到商品圖片的坐標(biāo)(用于計(jì)算動(dòng)畫開(kāi)始的坐標(biāo))

int

startLoc[]

=

new

int[2];

imageView.getLocationInWindow(startLoc);

//得到購(gòu)物車圖片的坐標(biāo)(用于計(jì)算動(dòng)畫結(jié)束后的坐標(biāo))

int

endLoc[]

=

new

int[2];

mCarImageView.getLocationInWindow(endLoc);

float

startX

=

startLoc[0]

-

parentLoc[0]

+

imageView.getWidth()/2;

float

startY

=

startLoc[1]

-

parentLoc[1]

+

imageView.getHeight()/2;

//商品掉落后的終點(diǎn)坐標(biāo):購(gòu)物車起始點(diǎn)-父布局起始點(diǎn)+購(gòu)物車圖片的1/5

float

toX

=

endLoc[0]

-

parentLoc[0]

+

mCarImageView.getWidth()

/

5;

float

toY

=

endLoc[1]

-

parentLoc[1];

//開(kāi)始繪制貝塞爾曲線

Path

path

=

new

Path();

path.moveTo(startX,

startY);

//使用二次薩貝爾曲線:注意第一個(gè)起始坐標(biāo)越大,貝塞爾曲線的橫向距離就會(huì)越大,一般按照下面的式子取即可

path.quadTo((startX

+

toX)

/

2,

startY,

toX,

toY);

mPathMeasure

=

new

PathMeasure(path,

false);

//屬性動(dòng)畫

ValueAnimator

valueAnimator

=

ValueAnimator.ofFloat(0,

mPathMeasure.getLength());

valueAnimator.setDuration(1000);

valueAnimator.setInterpolator(new

LinearInterpolator());

valueAnimator.addUpdateListener(new

ValueAnimator.AnimatorUpdateListener()

{

@Override

public

void

onAnimationUpdate(ValueAnimator

animation)

{

float

value

=

(float)animation.getAnimatedValue();

mPathMeasure.getPosTan(value,

mCurrentPosition,

null);

view.setTranslationX(mCurrentPosition[0]);

view.setTranslationY(mCurrentPosition[1]);

}

});

valueAnimator.addListener(new

Animator.AnimatorListener()

{

@Override

public

void

onAnimationStart(Animator

animation)

{

}

@Override

public

void

onAnimationEnd(Animator

animation)

{

//

購(gòu)物車的數(shù)量加1

mCount++;

mCountTv.setText(String.valueOf(mCount));

//

把移動(dòng)的圖片imageview從父布局里移除

mRootRl.removeView(view);

//shopImg

開(kāi)始一個(gè)放大動(dòng)畫

Animation

scaleAnim

=

AnimationUtils.loadAnimation(GoodsListActivity.this,

R.anim.shop_

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論