【移动应用开发技术】android如何实现直播点赞飘心动画效果_第1页
【移动应用开发技术】android如何实现直播点赞飘心动画效果_第2页
【移动应用开发技术】android如何实现直播点赞飘心动画效果_第3页
【移动应用开发技术】android如何实现直播点赞飘心动画效果_第4页
【移动应用开发技术】android如何实现直播点赞飘心动画效果_第5页
已阅读5页,还剩17页未读 继续免费阅读

下载本文档

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

文档简介

【移动应用开发技术】android如何实现直播点赞飘心动画效果

这篇文章给大家分享的是有关android如何实现直播点赞飘心动画效果的内容。在下觉得挺实用的,因此分享给大家做个参考,一起跟随在下过来看看吧。前段时间在写直播的时候,需要观众在看直播的时候点赞的效果,在此参照了腾讯大神写的点赞(飘心动画效果)。下面是效果图:1.自定义飘心动画的属性在attrs.xml中增加自定义的属性<!--

飘心动画自定义的属性

-->

<declare-styleable

name="HeartLayout">

<attr

name="initX"

format="dimension"/>

<attr

name="initY"

format="dimension"/>

<attr

name="xRand"

format="dimension"/>

<attr

name="animLengthRand"

format="dimension"/>

<attr

name="xPointFactor"

format="dimension"/>

<attr

name="animLength"

format="dimension"/>

<attr

name="heart_width"

format="dimension"/>

<attr

name="heart_height"

format="dimension"/>

<attr

name="bezierFactor"

format="integer"/>

<attr

name="anim_duration"

format="integer"/>

</declare-styleable>2.定义飘心默认值2.1dimens.xml<!--

飘星

-->

<dimen

name="heart_anim_bezier_x_rand">50.0dp</dimen>

<dimen

name="heart_anim_init_x">50.0dp</dimen>

<dimen

name="heart_anim_init_y">25.0dp</dimen>

<dimen

name="heart_anim_length">400.0dp</dimen>

<dimen

name="heart_anim_length_rand">350.0dp</dimen>

<dimen

name="heart_anim_x_point_factor">30.0dp</dimen>

<dimen

name="heart_size_height">27.3dp</dimen>

<dimen

name="heart_size_width">32.5dp</dimen>2.2integers.xml<?xml

version="1.0"

encoding="utf-8"?>

<resources>

<integer

name="heart_anim_bezier_factor">6</integer>

<integer

name="anim_duration">3000</integer>

</resources>3.定义飘心动画控制器3.1AbstractPathAnimator.javapublic

abstract

class

AbstractPathAnimator

{

private

final

Random

mRandom;

protected

final

Config

mConfig;

public

AbstractPathAnimator(Config

config)

{

mConfig

=

config;

mRandom

=

new

Random();

}

public

float

randomRotation()

{

return

mRandom.nextFloat()

*

28.6F

-

14.3F;

}

public

Path

createPath(AtomicInteger

counter,

View

view,

int

factor)

{

Random

r

=

mRandom;

int

x

=

r.nextInt(mConfig.xRand);

int

x2

=

r.nextInt(mConfig.xRand);

int

y

=

view.getHeight()

-

mConfig.initY;

int

y2

=

Value()

*

15

+

mConfig.animLength

*

factor

+

r.nextInt(mConfig.animLengthRand);

factor

=

y2

/

mConfig.bezierFactor;

x

=

mConfig.xPointFactor

+

x;

x2

=

mConfig.xPointFactor

+

x2;

int

y3

=

y

-

y2;

y2

=

y

-

y2

/

2;

Path

p

=

new

Path();

p.moveTo(mConfig.initX,

y);

p.cubicTo(mConfig.initX,

y

-

factor,

x,

y2

+

factor,

x,

y2);

p.moveTo(x,

y2);

p.cubicTo(x,

y2

-

factor,

x2,

y3

+

factor,

x2,

y3);

return

p;

}

public

abstract

void

start(View

child,

ViewGroup

parent);

public

static

class

Config

{

public

int

initX;

public

int

initY;

public

int

xRand;

public

int

animLengthRand;

public

int

bezierFactor;

public

int

xPointFactor;

public

int

animLength;

public

int

heartWidth;

public

int

heartHeight;

public

int

animDuration;

static

public

Config

fromTypeArray(TypedArray

typedArray,

float

x,

float

y,

int

pointx,

int

heartWidth,

int

heartHeight)

{

Config

config

=

new

Config();

Resources

res

=

typedArray.getResources();

config.initX

=

(int)

typedArray.getDimension(R.styleable.HeartLayout_initX,

x);

config.initY

=

(int)

typedArray.getDimension(R.styleable.HeartLayout_initY,

y);

config.xRand

=

(int)

typedArray.getDimension(R.styleable.HeartLayout_xRand,

res.getDimensionPixelOffset(R.dimen.heart_anim_bezier_x_rand));

config.animLength

=

(int)

typedArray.getDimension(R.styleable.HeartLayout_animLength,

res.getDimensionPixelOffset(R.dimen.heart_anim_length));//动画长度

config.animLengthRand

=

(int)

typedArray.getDimension(R.styleable.HeartLayout_animLengthRand,

res.getDimensionPixelOffset(R.dimen.heart_anim_length_rand));

config.bezierFactor

=

typedArray.getInteger(R.styleable.HeartLayout_bezierFactor,

res.getInteger(R.integer.heart_anim_bezier_factor));

config.xPointFactor

=

pointx;

//

config.heartWidth

=

(int)

typedArray.getDimension(R.styleable.HeartLayout_heart_width,

//

res.getDimensionPixelOffset(R.dimen.heart_size_width));//动画图片宽度

//

config.heartHeight

=

(int)

typedArray.getDimension(R.styleable.HeartLayout_heart_height,

//

res.getDimensionPixelOffset(R.dimen.heart_size_height));//动画图片高度

config.heartWidth

=

heartWidth;

config.heartHeight

=

heartHeight;

config.animDuration

=

typedArray.getInteger(R.styleable.HeartLayout_anim_duration,

res.getInteger(R.integer.anim_duration));//持续期

return

config;

}

}

}3.2PathAnimator.java/**

*

飘心路径动画器

*/

public

class

PathAnimator

extends

AbstractPathAnimator

{

private

final

AtomicInteger

mCounter

=

new

AtomicInteger(0);

private

Handler

mHandler;

public

PathAnimator(Config

config)

{

super(config);

mHandler

=

new

Handler(Looper.getMainLooper());

}

@Override

public

void

start(final

View

child,

final

ViewGroup

parent)

{

parent.addView(child,

new

ViewGroup.LayoutParams(mConfig.heartWidth,

mConfig.heartHeight));

FloatAnimation

anim

=

new

FloatAnimation(createPath(mCounter,

parent,

2),

randomRotation(),

parent,

child);

anim.setDuration(mConfig.animDuration);

anim.setInterpolator(new

LinearInterpolator());

anim.setAnimationListener(new

Animation.AnimationListener()

{

@Override

public

void

onAnimationEnd(Animation

animation)

{

mHandler.post(new

Runnable()

{

@Override

public

void

run()

{

parent.removeView(child);

}

});

mCounter.decrementAndGet();

}

@Override

public

void

onAnimationRepeat(Animation

animation)

{

}

@Override

public

void

onAnimationStart(Animation

animation)

{

mCounter.incrementAndGet();

}

});

anim.setInterpolator(new

LinearInterpolator());

child.startAnimation(anim);

}

static

class

FloatAnimation

extends

Animation

{

private

PathMeasure

mPm;

private

View

mView;

private

float

mDistance;

private

float

mRotation;

public

FloatAnimation(Path

path,

float

rotation,

View

parent,

View

child)

{

mPm

=

new

PathMeasure(path,

false);

mDistance

=

mPm.getLength();

mView

=

child;

mRotation

=

rotation;

parent.setLayerType(View.LAYER_TYPE_HARDWARE,

null);

}

@Override

protected

void

applyTransformation(float

factor,

Transformation

transformation)

{

Matrix

matrix

=

transformation.getMatrix();

mPm.getMatrix(mDistance

*

factor,

matrix,

PathMeasure.POSITION_MATRIX_FLAG);

mView.setRotation(mRotation

*

factor);

float

scale

=

1F;

if

(3000.0F

*

factor

<

200.0F)

{

scale

=

scale(factor,

0.0D,

0.06666667014360428D,

0.20000000298023224D,

1.100000023841858D);

}

else

if

(3000.0F

*

factor

<

300.0F)

{

scale

=

scale(factor,

0.06666667014360428D,

0.10000000149011612D,

1.100000023841858D,

1.0D);

}

mView.setScaleX(scale);

mView.setScaleY(scale);

transformation.setAlpha(1.0F

-

factor);

}

}

private

static

float

scale(double

a,

double

b,

double

c,

double

d,

double

e)

{

return

(float)

((a

-

b)

/

(c

-

b)

*

(e

-

d)

+

d);

}

}4.定义飘心界面4.1HeartView.java/**

*

飘心动画的界面

*/

public

class

HeartView

extends

ImageView{

//绘制的时候抗锯齿

private

static

final

Paint

sPaint

=

new

Paint(Paint.ANTI_ALIAS_FLAG

|

Paint.FILTER_BITMAP_FLAG);

private

static

final

Canvas

sCanvas

=

new

Canvas();

private

int

mHeartResId

=

R.drawable.heart0;

private

int

mHeartBorderResId

=

R.drawable.heart1;

private

static

Bitmap

sHeart;

private

static

Bitmap

sHeartBorder;

public

HeartView(Context

context)

{

super(context);

}

public

HeartView(Context

context,

AttributeSet

attrs)

{

super(context,

attrs);

}

public

HeartView(Context

context,

AttributeSet

attrs,

int

defStyleAttr)

{

super(context,

attrs,

defStyleAttr);

}

public

void

setDrawable(int

resourceId){

Bitmap

heart

=

BitmapFactory.decodeResource(getResources(),

resourceId);

//

Sets

a

drawable

as

the

content

of

this

ImageView.

setImageDrawable(new

BitmapDrawable(getResources(),heart));

}

public

void

setColor(int

color)

{

Bitmap

heart

=

createHeart(color);

setImageDrawable(new

BitmapDrawable(getResources(),

heart));

}

public

void

setColorAndDrawables(int

color,

int

heartResId,

int

heartBorderResId)

{

if

(heartResId

!=

mHeartResId)

{

sHeart

=

null;

}

if

(heartBorderResId

!=

mHeartBorderResId)

{

sHeartBorder

=

null;

}

mHeartResId

=

heartResId;

mHeartBorderResId

=

heartBorderResId;

setColor(color);

}

public

Bitmap

createHeart(int

color)

{

if

(sHeart

==

null)

{

sHeart

=

BitmapFactory.decodeResource(getResources(),

mHeartResId);

}

if

(sHeartBorder

==

null)

{

sHeartBorder

=

BitmapFactory.decodeResource(getResources(),

mHeartBorderResId);

}

Bitmap

heart

=

sHeart;

Bitmap

heartBorder

=

sHeartBorder;

Bitmap

bm

=

createBitmapSafely(heartBorder.getWidth(),

heartBorder.getHeight());

if

(bm

==

null)

{

return

null;

}

Canvas

canvas

=

sCanvas;

canvas.setBitmap(bm);

Paint

p

=

sPaint;

canvas.drawBitmap(heartBorder,

0,

0,

p);

p.setColorFilter(new

PorterDuffColorFilter(color,

PorterDuff.Mode.SRC_ATOP));

float

dx

=

(heartBorder.getWidth()

-

heart.getWidth())

/

2f;

float

dy

=

(heartBorder.getHeight()

-

heart.getHeight())

/

2f;

canvas.drawBitmap(heart,

dx,

dy,

p);

p.setColorFilter(null);

canvas.setBitmap(null);

return

bm;

}

private

static

Bitmap

createBitmapSafely(int

width,

int

height)

{

try

{

return

Bitmap.createBitmap(width,

height,

Bitmap.Config.ARGB_8888);

}

catch

(OutOfMemoryError

error)

{

error.printStackTrace();

}

return

null;

}

}4.2飘心动画路径布局HeartLayout.java/**

*

飘心动画路径

*/

public

class

HeartLayout

extends

RelativeLayout

implements

View.OnClickListener

{

private

AbstractPathAnimator

mAnimator;

private

AttributeSet

attrs

=

null;

private

int

defStyleAttr

=

0;

private

OnHearLayoutListener

onHearLayoutListener;

private

static

HeartHandler

heartHandler;

private

static

HeartThread

heartThread;

public

void

setOnHearLayoutListener(OnHearLayoutListener

onHearLayoutListener)

{

this.onHearLayoutListener

=

onHearLayoutListener;

}

public

interface

OnHearLayoutListener

{

boolean

onAddFavor();

}

public

HeartLayout(Context

context)

{

super(context);

findViewById(context);

}

public

HeartLayout(Context

context,

AttributeSet

attrs)

{

super(context,

attrs);

this.attrs

=

attrs;

findViewById(context);

}

public

HeartLayout(Context

context,

AttributeSet

attrs,

int

defStyleAttr)

{

super(context,

attrs,

defStyleAttr);

this.attrs

=

attrs;

this.defStyleAttr

=

defStyleAttr;

findViewById(context);

}

private

Bitmap

bitmap;

private

void

findViewById(Context

context)

{

LayoutInflater.from(context).inflate(R.layout.ly_periscope,

this);

bitmap

=

BitmapFactory.decodeResource(getResources(),

R.drawable.icon_like);

dHeight

=

bitmap.getWidth()/2;

dWidth

=

bitmap.getHeight()/2;

textHight

=

sp2px(getContext(),

20)

+

dHeight

/

2;

pointx

=

dWidth;//随机上浮方向的x坐标

bitmap.recycle();

}

private

int

mHeight;

private

int

mWidth;

private

int

textHight;

private

int

dHeight;

private

int

dWidth;

private

int

initX;

private

int

pointx;

public

static

int

sp2px(Context

context,

float

spValue)

{

final

float

fontScale

=

context.getResources().getDisplayMetrics().scaledDensity;

return

(int)

(spValue

*

fontScale

+

0.5f);

}

public

class

HeartHandler

extends

Handler

{

public

final

static

int

MSG_SHOW

=

1;

WeakReference<HeartLayout>

wf;

public

HeartHandler(HeartLayout

layout)

{

wf

=

new

WeakReference<HeartLayout>(layout);

}

@Override

public

void

handleMessage(Message

msg)

{

super.handleMessage(msg);

HeartLayout

layout

=

wf.get();

if

(layout

==

null)

return;

switch

(msg.what)

{

case

MSG_SHOW:

addFavor();

break;

}

}

}

public

class

HeartThread

implements

Runnable

{

private

long

time

=

0;

private

int

allSize

=

0;

public

void

addTask(long

time,

int

size)

{

this.time

=

time;

allSize

+=

size;

}

public

void

clean()

{

allSize

=

0;

}

@Override

public

void

run()

{

if

(heartHandler

==

null)

return;

if

(allSize

>

0)

{

heartHandler.sendEmptyMessage(HeartHandler.MSG_SHOW);

allSize--;

}

postDelayed(this,

time);

}

}

private

void

init(AttributeSet

attrs,

int

defStyleAttr)

{

final

TypedArray

a

=

getContext().obtainStyledAttributes(

attrs,

R.styleable.HeartLayout,

defStyleAttr,

0);

if

(pointx

<=

initX

&&

pointx

>=

0)

{

pointx

-=

10;

}

else

if

(pointx

>=

-initX

&&

pointx

<=

0)

{

pointx

+=

10;

}

else

pointx

=

initX;

mAnimator

=

new

PathAnimator(AbstractPathAnimator.Config.fromTypeArray(a,

initX,

textHight,

pointx,

dWidth,

dHeight));

a.recycle();

}

@Override

protected

void

onMeasure(int

widthMeasureSpec,

int

heightMeasureSpec)

{

super.onMeasure(widthMeasureSpec,

heightMeasureSpec);

//获取本身的宽高

这里要注意,测量之后才有宽高

mWidth

=

getMeasuredWidth();

mHeight

=

getMeasuredHeight();

initX

=

mWidth

/

2

-

dWidth

/

2;

}

public

AbstractPathAnimator

getAnimator()

{

return

mAnimator;

}

public

void

setAnimator(AbstractPathAnimator

animator)

{

clearAnimation();

mAnimator

=

animator;

}

public

void

clearAnimation()

{

for

(int

i

=

0;

i

<

getChildCount();

i++)

{

getChildAt(i).clearAnimation();

}

removeAllViews();

}

private

static

int[]

drawableIds

=

new

int[]{R.drawable.heart0,

R.drawable.heart1,

R.drawable.heart2,

R.drawable.heart3,

R.drawable.heart4,

R.drawable.heart5,

R.drawable.heart6,

R.drawable.heart7,

R.drawable.heart8,};

private

Random

random

=

new

Random();

public

void

addFavor()

{

HeartView

heartView

=

new

HeartView(getContext());

heartView.setDrawable(drawableIds[random.nextInt(8)]);

init(attrs,

defStyleAttr);

mAnimator.start(heartView,

this);

}

private

long

nowTime,

lastTime;

final

static

int[]

sizeTable

=

{9,

99,

999,

9999,

99999,

999999,

9999999,

99999999,

999999999,

Integer.MAX_VALUE};

public

static

int

sizeOfInt(int

x)

{

for

(int

i

=

0;

;

i++)

if

(x

<=

sizeTable[i])

return

i

+

1;

}

public

void

addFavor(int

size)

{

switch

(sizeOfInt(size))

{

case

1:

size

=

size

%

10;

break;

default:

size

=

size

%

100;

}

if

(size

==

0)

return;

nowTime

=

System.currentTimeMillis();

long

time

=

nowTime

-

lastTime;

if

(lastTime

==

0)

time

=

2

*

1000;//第一次分为2秒显示完

time

=

time

/

(size

+

15);

if

(heartThread

==

null)

{

heartThread

=

new

HeartThread();

}

if

(heartHandler

==

null)

{

heartHandler

=

new

HeartHandler(this);

heartHandler.post(heartThread);

}

heartThread.addTask(time,

size);

lastTime

=

nowTime;

}

public

void

addHeart(int

color)

{

HeartView

heartView

=

new

HeartView(getContext());

heartView.setColor(color);

init(attrs,

defStyleAttr);

mAnimator.start(heartView,

this);

}

public

void

addHeart(int

color,

int

heartResId,

int

heartBorderResId)

{

HeartView

heartView

=

new

HeartView(getContext());

heartView.setColorAndDrawables(color,

heartResId,

heartBorderResId);

init(attrs,

defStyleAttr);

mAnimator.start(heartView,

this);

}

@Override

public

void

onClick(View

v)

{

int

i

=

v.getId();

if

(i

==

R.id.img)

{

if

(onHearLayoutListener

!=

null)

{

boolean

isAdd

=

onHearLayoutLis

温馨提示

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

评论

0/150

提交评论