模仿美团抛物线效果

以前在毕业设计里用到了类似美团抛物线的效果,当时是找的网上的一个例子,最近有时间自己实现了一个,也算是弥补了一下心里的遗憾。
实现思路:点击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[2];
                view.getLocationOnScreen(location);
                int x = location[0];
                int y = location[1];
                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[2];
        iv_end.getLocationOnScreen(location);
        int endX = location[0];
        int endY = location[1];
        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(1000);
        ObjectAnimator y1 = ObjectAnimator.ofFloat(imageView, "y", (float) coordinateY, (float) (coordinateY - 100));
        y1.setInterpolator(new DecelerateInterpolator());
        y1.setDuration(400);
        ObjectAnimator y2 = ObjectAnimator.ofFloat(imageView, "y", (float) (coordinateY - 100), endY);
        y2.setInterpolator(new AccelerateInterpolator());
        y2.setDuration(600);
        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 = 0;
        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            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。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本课程讲了Vue3+Vue2+Uni-app(uniapp)入门基础与实战,其中还重点讲解了ES6、TypeScript这些基础知识,实战由两大价值5000元的真实企业级项目组成,分别是仿京东电商网站和仿美团微信点餐小程序,同时两大项目代码全部赠送,还赠送前后端架构模板,工作中直接使用。VUE和uni-app是目前热门的前端框架,本课程教你如何快速学会VUE和uni-app并应用到实战,教你如何解决内存泄漏,常用UI库的使用,自己封装组件和插件,正式上线白屏问题,性能优化、解决iphoneX“刘海”兼容性问题、微信支付、微信授权登录,获取位置在地上显示,获取用户所在的城市和街道信息,微信小程序发布审核等。对正在工作当中或打算学习VUE和uni-app高薪就业的你来说,那么这门课程便是你手中的葵花宝典。学习技巧:学习当中不要只看,一定要多敲代码,如果碰到某一个知识点不是很明白,不要钻牛角尖,千万不要因为一个点,放弃整个森林,接着往下学,硬着头皮开发项目。只要能亲自开发一个完整的项目,你会发现不明白的地方自然而然就明白了,项目做出来就真正的学会了。此vue和uni-app课程以面试和实战为基础进行讲解,每个知识点都会让你知道在实际项目开发中如何使用,学习后,可以开发大型项目,增强逻辑思维,至少让你拥有3年以上开发经验的实力!代码和ppt均可下载!免费提供《企业级完整实战项目接口文档》,绝对可用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值