我目前正在使用消息传递应用程序,我希望将新用户显示为动态飞行图标,例如facebook实时浮动反应。任何人都可以启发我应该遵循的流程或任何有用的图书馆链接吗?
我已经尝试浏览并检查了一些图书馆链接,例如this1和this2,但这些与facebook live reaction pack不相似。
答案 0 :(得分:1)
我也问过您同样的问题,但是我没有找到与Android类似的东西,所以我决定自己做。
我在Android Studio中创建了这个项目,该项目基于我在YouTube上找到的Swift教程,您可以通过点击here来看到它。
我使用Path
类绘制气泡或图像(ImageView
)所遵循的路径,并使用ObjectAnimator
通过该路径初始化动画。
最后,我使用Rand
来随机化路径的值,以使其外观与Facebook Live更相似,而不仅是沿着所有气泡或图像遵循相同的路径。
以下是我在Android Studio中的项目演示的视频:Here!
答案 1 :(得分:1)
我已经通过修改旧代码实现了这一点,这是我的解决方案。您可以更改表情符号的方向和数量,也可以使其在任何视图上方或下方飞行。
主xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="top|left"
android:orientation="vertical">
<FrameLayout
android:id="@+id/animation_holder"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
主要活动
package com.example.hamidraza.flyinemojis;
import android.app.Activity;
import android.os.Bundle;
import android.view.ViewGroup;
import android.view.animation.Animation;
public class MainActivity extends Activity {
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
setContentView(R.layout.activity_main);
emoji_one();
emoji_two();
emoji_three();
}
public void flyEmoji(final int resId) {
ZeroGravityAnimation animation = new ZeroGravityAnimation();
animation.setCount(1);
animation.setScalingFactor(0.2f);
animation.setOriginationDirection(Direction.BOTTOM);
animation.setDestinationDirection(Direction.TOP);
animation.setImage(resId);
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
}
);
ViewGroup container = findViewById(R.id.animation_holder);
animation.play(this,container);
}
public void emoji_one() {
// You can change the number of emojis that will be flying on screen
for (int i = 0; i < 5; i++) {
flyEmoji(R.drawable.emojis1);
}
}
// You can change the number of emojis that will be flying on screen
public void emoji_two(){
for(int i=0;i<5;i++) {
flyEmoji(R.drawable.dabemoji);
}
}
// You can change the number of emojis that will be flying on screen
public void emoji_three(){
for(int i=0;i<5;i++) {
flyEmoji(R.drawable.heart);
}
}
// This method will be used if You want to fly your Emois Over any view
// public void flyObject(final int resId, final int duration, final Direction from, final Direction to, final float scale) {
//
// ZeroGravityAnimation animation = new ZeroGravityAnimation();
// animation.setCount(1);
// animation.setScalingFactor(scale);
// animation.setOriginationDirection(from);
// animation.setDestinationDirection(to);
// animation.setImage(resId);
// animation.setDuration(duration);
// animation.setAnimationListener(new Animation.AnimationListener() {
// @Override
// public void onAnimationStart(Animation animation) {
//
// }
//
// @Override
// public void onAnimationEnd(Animation animation) {
//
// flyObject(resId, duration, from, to, scale);
// }
//
// @Override
// public void onAnimationRepeat(Animation animation) {
//
// }
// });
//
// ViewGroup container = (ViewGroup) findViewById(R.id.animation_bigger_objects_holder);
// animation.play(this,container);
//
// }
//
}
ZeroGravityAnimation
package com.example.hamidraza.flyinemojis;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.FrameLayout;
public class ZeroGravityAnimation {
private static final int RANDOM_DURATION = -1;
private Direction mOriginationDirection = Direction.RANDOM;
private Direction mDestinationDirection = Direction.RANDOM;
private int mDuration = RANDOM_DURATION;
private int mCount = 1;
private int mImageResId;
private float mScalingFactor = 1f;
private Animation.AnimationListener mAnimationListener;
/**
* Sets the orignal direction. The animation will originate from the given direction.
*/
public ZeroGravityAnimation setOriginationDirection(Direction direction) {
this.mOriginationDirection = direction;
return this;
}
/**
* Sets the animation destination direction. The translate animation will proceed towards the given direction.
* @param direction
* @return
*/
public ZeroGravityAnimation setDestinationDirection(Direction direction) {
this.mDestinationDirection = direction;
return this;
}
/**
* Will take a random time duriation for the animation
* @return
*/
public ZeroGravityAnimation setRandomDuration() {
return setDuration(RANDOM_DURATION);
}
/**
* Sets the time duration in millseconds for animation to proceed.
* @param duration
* @return
*/
public ZeroGravityAnimation setDuration(int duration) {
this.mDuration = duration;
return this;
}
/**
* Sets the image reference id for drawing the image
* @param resId
* @return
*/
public ZeroGravityAnimation setImage(int resId) {
this.mImageResId = resId;
return this;
}
/**
* Sets the image scaling value.
* @param scale
* @return
*/
public ZeroGravityAnimation setScalingFactor(float scale) {
this.mScalingFactor = scale;
return this;
}
public ZeroGravityAnimation setAnimationListener(Animation.AnimationListener listener) {
this.mAnimationListener = listener;
return this;
}
public ZeroGravityAnimation setCount(int count) {
this.mCount = count;
return this;
}
/**
* Starts the Zero gravity animation by creating an OTT and attach it to th given ViewGroup
* @param activity
* @param ottParent
*/
public void play(Activity activity, ViewGroup ottParent) {
DirectionGenerator generator = new DirectionGenerator();
if(mCount > 0) {
for (int i = 0; i < mCount; i++) {
final int iDupe = i;
Direction origin = mOriginationDirection == Direction.RANDOM ? generator.getRandomDirection() : mOriginationDirection;
Direction destination = mDestinationDirection == Direction.RANDOM ? generator.getRandomDirection(origin) : mDestinationDirection;
int startingPoints[] = generator.getPointsInDirection(activity, origin);
int endPoints[] = generator.getPointsInDirection(activity,destination);
Bitmap bitmap = BitmapFactory.decodeResource(activity.getResources(), mImageResId);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, (int) (bitmap.getWidth() * mScalingFactor), (int) (bitmap.getHeight() * mScalingFactor), false);
switch (origin) {
case LEFT:
startingPoints[0] -= scaledBitmap.getWidth();
break;
case RIGHT:
startingPoints[0] += scaledBitmap.getWidth();
break;
case TOP:
startingPoints[1] -= scaledBitmap.getHeight();
break;
case BOTTOM:
startingPoints[1] += scaledBitmap.getHeight();
break;
}
switch (destination) {
case LEFT:
endPoints[0] -= scaledBitmap.getWidth();
break;
case RIGHT:
endPoints[0] += scaledBitmap.getWidth();
break;
case TOP:
endPoints[1] -= scaledBitmap.getHeight();
break;
case BOTTOM:
endPoints[1] += scaledBitmap.getHeight();
break;
}
final OverTheTopLayer layer = new OverTheTopLayer();
FrameLayout ottLayout = layer.with(activity)
.scale(mScalingFactor)
.attachTo(ottParent)
.setBitmap(scaledBitmap, startingPoints)
.create();
switch (origin) {
case LEFT:
}
int deltaX = endPoints[0] - startingPoints[0];
int deltaY = endPoints[1] - startingPoints[1];
int duration = mDuration;
if (duration == RANDOM_DURATION) {
duration = RandomUtil.generateRandomBetween(3500, 12500);
}
TranslateAnimation animation = new TranslateAnimation(0, deltaX, 0, deltaY);
animation.setDuration(duration);
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
if (iDupe == 0) {
if (mAnimationListener != null) {
mAnimationListener.onAnimationStart(animation);
}
}
}
@Override
public void onAnimationEnd(Animation animation) {
layer.destroy();
if (iDupe == (mCount - 1)) {
if (mAnimationListener != null) {
mAnimationListener.onAnimationEnd(animation);
}
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
layer.applyAnimation(animation);
}
}
else {
Log.e(ZeroGravityAnimation.class.getSimpleName(),"Count was not provided, animation was not started");
}
}
/**
* Takes the content view as view parent for laying the animation objects and starts the animation.
* @param activity - activity on which the zero gravity animation should take place.
*/
public void play(Activity activity) {
play(activity,null);
}
}
RandomUtils Java类
package com.example.hamidraza.flyinemojis;
import java.util.Random;
public class RandomUtil {
/**
* Generates the random between two given integers.
*/
public static int generateRandomBetween(int start, int end) {
Random random = new Random();
int rand = random.nextInt(Integer.MAX_VALUE - 1) % end;
if (rand < start) {
rand = start;
}
return rand;
}
}
方向
package com.example.hamidraza.flyinemojis;
public enum Direction {
TOP, LEFT, RIGHT, BOTTOM,RANDOM
}
DirectionGeneretor
package com.example.hamidraza.flyinemojis;
import android.app.Activity;
import java.util.Random;
public class DirectionGenerator {
/**
* Gets the random pixel points in the given direction of the screen
* @param activity - activity from where you are referring the random value.
* @param direction - on among LEFT,RIGHT,TOP,BOTTOM,RANDOM
* @return a pixel point {x,y} in the given direction.
*/
public int[] getPointsInDirection(Activity activity, Direction direction) {
switch (direction) {
case LEFT:
return getRandomLeft(activity);
case RIGHT:
return getRandomRight(activity);
case BOTTOM:
return getRandomBottom(activity);
case TOP:
return getRandomTop(activity);
default:
Direction[] allDirections = new Direction[]{Direction.LEFT,Direction.TOP,Direction.BOTTOM,Direction.RIGHT};
int index = new Random().nextInt(allDirections.length);
return getPointsInDirection(activity, allDirections[index]);
}
}
/**
* Gets the random pixel points in the left direction of the screen. The value will be of {0,y} where y will be a random value.
* @param activity - activity from where you are referring the random value.
* @return a pixel point {x,y}.
*/
public int[] getRandomLeft(Activity activity) {
int x = 0;
int height = activity.getResources().getDisplayMetrics().heightPixels;
Random random = new Random();
int y = random.nextInt(height);
return new int[]{x, y};
}
/**
* Gets the random pixel points in the top direction of the screen. The value will be of {x,0} where x will be a random value.
* @param activity - activity from where you are referring the random value.
* @return a pixel point {x,y}.
*/
public int[] getRandomTop(Activity activity) {
int y = 0;
int width = activity.getResources().getDisplayMetrics().widthPixels;
Random random = new Random();
int x = random.nextInt(width);
return new int[]{x, y};
}
/**
* Gets the random pixel points in the right direction of the screen. The value will be of {screen_width,y} where y will be a random value.
* @param activity - activity from where you are referring the random value.
* @return a pixel point {x,y}.
*/
public int[] getRandomRight(Activity activity) {
int width = activity.getResources().getDisplayMetrics().widthPixels;
int height = activity.getResources().getDisplayMetrics().heightPixels;
int x = width ;
Random random = new Random();
int y = random.nextInt(height);
return new int[]{x, y};
}
/**
* Gets the random pixel points in the bottom direction of the screen. The value will be of {x,screen_height} where x will be a random value.
* @param activity - activity from where you are referring the random value.
* @return a pixel point {x,y}.
*/
public int[] getRandomBottom(Activity activity) {
int width = activity.getResources().getDisplayMetrics().widthPixels;
int height = activity.getResources().getDisplayMetrics().heightPixels;
int y = height ;
Random random = new Random();
int x = random.nextInt(width);
return new int[]{x, y};
}
/**
* Gets a random direction.
* @return one among LEFT,RIGHT,BOTTOM,TOP
*/
public Direction getRandomDirection() {
Direction[] allDirections = new Direction[]{Direction.LEFT,Direction.TOP,Direction.BOTTOM,Direction.RIGHT};
int index = new Random().nextInt(allDirections.length);
return (allDirections[index]);
}
/**
* Gets a random direction skipping the given direction.
* @param toSkip a direction which should not be returned by this method.
* @return one among LEFT,RIGHT,BOTTOM if TOP is provided as direction to skip,
* one among TOP,RIGHT,BOTTOM if LEFT is provided as direction to skip
* and so on.
*/
public Direction getRandomDirection(Direction toSkip) {
Direction[] allExceptionalDirections;
switch (toSkip) {
case LEFT:
allExceptionalDirections = new Direction[]{Direction.TOP,Direction.BOTTOM,Direction.RIGHT};
break;
case RIGHT:
allExceptionalDirections = new Direction[]{Direction.TOP,Direction.BOTTOM,Direction.LEFT};
break;
case BOTTOM:
allExceptionalDirections = new Direction[]{Direction.TOP,Direction.LEFT,Direction.RIGHT};
break;
case TOP:
allExceptionalDirections = new Direction[]{Direction.LEFT,Direction.BOTTOM,Direction.RIGHT};
break;
default:
allExceptionalDirections = new Direction[]{Direction.LEFT,Direction.TOP,Direction.BOTTOM,Direction.RIGHT};
}
int index = new Random().nextInt(allExceptionalDirections.length);
return (allExceptionalDirections[index]);
}
}
OverTheTopLayer 这将有助于使表情符号飞过某些视图
package com.example.hamidraza.flyinemojis;
import android.app.Activity;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.widget.FrameLayout;
import android.widget.ImageView;
import java.lang.ref.WeakReference;
public class OverTheTopLayer {
public static class OverTheTopLayerException extends RuntimeException {
public OverTheTopLayerException(String msg) {
super(msg);
}
}
private WeakReference<Activity> mWeakActivity;
private WeakReference<ViewGroup> mWeakRootView;
private FrameLayout mCreatedOttLayer;
private float mScalingFactor = 1.0f;
private int[] mDrawLocation = {0, 0};
private Bitmap mBitmap;
public OverTheTopLayer() {
}
/**
* To create a layer on the top of activity
*/
public OverTheTopLayer with(Activity weakReferenceActivity) {
mWeakActivity = new WeakReference<Activity>(weakReferenceActivity);
return this;
}
/**
* Draws the image as per the drawable resource id on the given location pixels.
*/
public OverTheTopLayer generateBitmap(Resources resources, int drawableResId, float mScalingFactor, int[] location) {
if (location == null) {
location = new int[]{0, 0};
} else if (location.length != 2) {
throw new OverTheTopLayerException("Requires location as an array of length 2 - [x,y]");
}
Bitmap bitmap = BitmapFactory.decodeResource(resources, drawableResId);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, (int) (bitmap.getWidth() * mScalingFactor), (int) (bitmap.getHeight() * mScalingFactor), false);
this.mBitmap = scaledBitmap;
this.mDrawLocation = location;
return this;
}
public OverTheTopLayer setBitmap(Bitmap bitmap, int[] location) {
if (location == null) {
location = new int[]{0, 0};
} else if (location.length != 2) {
throw new OverTheTopLayerException("Requires location as an array of length 2 - [x,y]");
}
this.mBitmap = bitmap;
this.mDrawLocation = location;
return this;
}
/**
* Holds the scaling factor for the image.
*
* @param scale
* @return
*/
public OverTheTopLayer scale(float scale) {
if (scale <= 0) {
throw new OverTheTopLayerException("Scaling should be > 0");
}
this.mScalingFactor = scale;
return this;
}
/**
* Attach the OTT layer as the child of the given root view.
* @return
*/
public OverTheTopLayer attachTo(ViewGroup rootView) {
this.mWeakRootView = new WeakReference<ViewGroup>(rootView);
return this;
}
/**
* Creates an OTT.
* @return
*/
public FrameLayout create() {
if(mCreatedOttLayer != null) {
destroy();
}
if (mWeakActivity == null) {
throw new OverTheTopLayerException("Could not create the layer as not activity reference was provided.");
}
Activity activity = mWeakActivity.get();
if (activity != null) {
ViewGroup attachingView = null;
if (mWeakRootView != null && mWeakRootView.get() != null) {
attachingView = mWeakRootView.get();
} else {
attachingView = (ViewGroup) activity.findViewById(android.R.id.content);
}
ImageView imageView = new ImageView(activity);
imageView.setImageBitmap(mBitmap);
int minWidth = mBitmap.getWidth();
int minHeight = mBitmap.getHeight();
imageView.measure(View.MeasureSpec.makeMeasureSpec(minWidth, View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(minHeight, View.MeasureSpec.AT_MOST));
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) imageView.getLayoutParams();
if (params == null) {
params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.TOP);
imageView.setLayoutParams(params);
}
int xPosition = mDrawLocation[0];
int yPosition = mDrawLocation[1];
params.width = minWidth;
params.height = minHeight;
params.leftMargin = xPosition;
params.topMargin = yPosition;
imageView.setLayoutParams(params);
FrameLayout ottLayer = new FrameLayout(activity);
FrameLayout.LayoutParams topLayerParam = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT, Gravity.TOP);
ottLayer.setLayoutParams(topLayerParam);
ottLayer.addView(imageView);
attachingView.addView(ottLayer);
mCreatedOttLayer = ottLayer;
} else {
Log.e(OverTheTopLayer.class.getSimpleName(), "Could not create the layer. Reference to the activity was lost");
}
return mCreatedOttLayer;
}
/**
* Kills the OTT
*/
public void destroy() {
if (mWeakActivity == null) {
throw new OverTheTopLayerException("Could not create the layer as not activity reference was provided.");
}
Activity activity = mWeakActivity.get();
if (activity != null) {
ViewGroup attachingView = null;
if (mWeakRootView != null && mWeakRootView.get() != null) {
attachingView = mWeakRootView.get();
} else {
attachingView = (ViewGroup) activity.findViewById(android.R.id.content);
}
if (mCreatedOttLayer != null) {
attachingView.removeView(mCreatedOttLayer);
mCreatedOttLayer = null;
}
} else {
Log.e(OverTheTopLayer.class.getSimpleName(), "Could not destroy the layer as the layer was never created.");
}
}
/**
* Applies the animation to the image view present in OTT.
* @param animation
*/
public void applyAnimation(Animation animation) {
if(mCreatedOttLayer != null) {
ImageView drawnImageView = (ImageView) mCreatedOttLayer.getChildAt(0);[enter image description here][1]
drawnImageView.startAnimation(animation);
}
}
}