以前在毕业设计里用到了类似美团抛物线的效果,当时是找的网上的一个例子,最近有时间自己实现了一个,也算是弥补了一下心里的遗憾。
实现思路:点击item中的按钮,在MainActivity中添加动画图片,添加的图片执行一个类似抛物线的动画,运动到底部指定位置。
我们先来看看运行效果:

动画效果的实现:
先贴出Adapter的代码:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
public interface OnClickLitener {
void onClick(int x, int y);
}
private OnClickLitener mOnClickLitener;
public void setOnClickLitener(OnClickLitener onClickLitener) {
this.mOnClickLitener = onClickLitener;
}
private Context context;
private String[] mDataset;
public static class ViewHolder extends RecyclerView.ViewHolder {
public LinearLayout item;
public TextView title;
public ImageView button;
public ViewHolder(LinearLayout v) {
super(v);
item = v;
}
}
public MyAdapter(Context context, String[] myDataset) {
mDataset = myDataset;
this.context = context;
}
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_view, parent, false);
ViewHolder vh = new ViewHolder((LinearLayout) v);
vh.title = (TextView) v.findViewById(R.id.title);
vh.button = (ImageView) v.findViewById(R.id.button);
return vh;
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.title.setText(mDataset[position]);
holder.button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int[] location = new int[];
view.getLocationOnScreen(location);
int x = location[];
int y = location[];
mOnClickLitener.onClick(x, y);
}
});
}
@Override
public int getItemCount() {
return mDataset.length;
}
}
Adapter中的代码很简单,其中item布局中只有一个TextView,跟一个Imageview,当点击ImageView时将ImageView在屏幕中的坐标传递给MainActivity。
下面是MainActivity的具体代码:
public class MainActivity extends AppCompatActivity implements MyAdapter.OnClickLitener {
private RecyclerView mRecyclerView;
private MyAdapter mAdapter;
private LinearLayoutManager linearLayoutManager;
private ImageView iv_end;
RelativeLayout mainLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
setSupportActionBar(myToolbar);
ActionBar ab = getSupportActionBar();
ab.setDisplayHomeAsUpEnabled(true);
iv_end = (ImageView) findViewById(R.id.end);
mainLayout = (RelativeLayout) findViewById(R.id.activity_main);
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
String[] myDataset = {"断", "桥", "残", "雪"};
mRecyclerView.setHasFixedSize(true);
linearLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(linearLayoutManager);
mAdapter = new MyAdapter(this, myDataset);
mRecyclerView.setAdapter(mAdapter);
mAdapter.setOnClickLitener(this);
}
@Override
public void onClick(int x, int y) {
Log.d("paowu", "onClick");
int[] location = new int[];
iv_end.getLocationOnScreen(location);
int endX = location[];
int endY = location[];
int height = getStatusBarHeight();
int coordinateX = x;
int coordinateY = y - height;
endY = endY - height;
final ImageView imageView = new ImageView(this);
imageView.setImageResource(R.mipmap.ic_launcher);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
layoutParams.leftMargin = coordinateX;
layoutParams.topMargin = coordinateY;
mainLayout.addView(imageView, layoutParams);
ObjectAnimator x1 = ObjectAnimator.ofFloat(imageView, "x", (float) coordinateX, endX);
x1.setDuration();
ObjectAnimator y1 = ObjectAnimator.ofFloat(imageView, "y", (float) coordinateY, (float) (coordinateY - ));
y1.setInterpolator(new DecelerateInterpolator());
y1.setDuration();
ObjectAnimator y2 = ObjectAnimator.ofFloat(imageView, "y", (float) (coordinateY - ), endY);
y2.setInterpolator(new AccelerateInterpolator());
y2.setDuration();
AnimatorSet set1 = new AnimatorSet();
set1.play(x1).with(y1);
set1.play(y2).after(y1);
set1.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
mainLayout.removeView(imageView);
}
});
set1.start();
}
/**
* 获取状态栏的高度
*
* @return
*/
public int getStatusBarHeight() {
int result = ;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > ) {
result = getResources().getDimensionPixelSize(resourceId);
}
return result;
}
}
MainActivity布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.jqk.meituananimation.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
<include layout="@layout/activity_main_content"></include>
</LinearLayout>
</RelativeLayout>
activity_main_content布局代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="9">
<android.support.v7.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:gravity="center_vertical"
android:layout_height="0dp"
android:layout_weight="1">
<ImageView
android:id="@+id/end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher" />
</LinearLayout>
</LinearLayout>
类似抛物线的动画由x轴动画和y轴动画组合而成,x轴是匀速直线运动;y轴动画分为两部分:上升和下降,为了达到减速跟加速的效果,使用了系统自带的两个插值器,然后将这三个动画按照一定的顺序组合起来,在动画结束时要将添加的图片移除。这样就达到了我们要的效果。
注意:
如果我们使用直接获取的坐标,我们会发现添加的图片跟实际的图片总会相差一个状态栏的高度,因此起始跟结束的y坐标都应减去状态栏的高度。我们是根据具体的坐标值添加的图片,因此MainActivity最外层的布局应是RelativeLayout。