GridLayout + Animation 实现 Android 仿超级课程表“发现”全屏宫格图标弹出动画

关于全屏宫格图标,超级课程表的“发现”是目前我见过的最好的解决方案,流畅的动画打破了布局单一带来的死板气氛。下面就来介绍这样的动画是如何实现的。

首先创建一个activity叫BiaoDiscoverActivity

此处用到了Handler,Handler主要用于异步消息的处理:当发出一个消息之后,首先进入一个消息队列,发送消息的函数即刻返回,而另外一个部分在消息队列中逐一将消息取出,然后对消息进行处理,也就是发送消息和接收消息不是同步的处理。 这种机制通常用来处理相对耗时比较长的操作

public class BiaoDiscoverActivity extends BaseActivity {

@Bind(R.id.ivBiaoClose)
ImageView mIvClose;
@Bind(R.id.rll\_found\_note)
AutoRelativeLayout mrllNote;
@Bind(R.id.rll\_found\_exam_time)
AutoRelativeLayout mrllExamTime;
@Bind(R.id.rll\_found\_class\_room\_search)
AutoRelativeLayout mrllClassroom;
@Bind(R.id.rll\_found\_score_search)
AutoRelativeLayout mrllScore;
@Bind(R.id.rll\_found\_super_act)
AutoRelativeLayout mrllSuperAct;
@Bind(R.id.rll\_found\_super_group)
AutoRelativeLayout mrllSuperGroup;
@Bind(R.id.rll\_found\_train_tickets)
AutoRelativeLayout mrllTrainTickets;
@Bind(R.id.rll\_found\_air_tickets)
AutoRelativeLayout mrllAirTickets;
@Bind(R.id.rll\_found\_school_recuit)
AutoRelativeLayout mrllSchoolRecuit;
@Bind(R.id.rll\_found\_house_rent)
AutoRelativeLayout mrllHouseRent;
@Bind(R.id.rll\_found\_entertainment_class)
AutoRelativeLayout mrllEntertainment;

//宫格图标
private List rllList;
private Handler handler;

@Override
protected BasePresenter createPresenter() {
    return null;
}

@Override
protected int provideContentViewId() {
    return R.layout.activity\_biao\_discover;
}


@Override
public void initView() {
    super.initView();
    initRll();
    initGrid();
    handler = new Handler();
}

private synchronized void initRll() {
    rllList = new ArrayList<>();
    rllList.add(mrllNote);
    rllList.add(mrllExamTime);
    rllList.add(mrllClassroom);
    rllList.add(mrllScore);
    rllList.add(mrllSuperAct);
    rllList.add(mrllSuperGroup);
    rllList.add(mrllTrainTickets);
    rllList.add(mrllAirTickets);
    rllList.add(mrllSchoolRecuit);
    rllList.add(mrllHouseRent);
    rllList.add(mrllEntertainment);
}

@Override
protected void onResume() {
    super.onResume();
    itemsAnimation();
}

private void initGrid() {
    for (int i = 0; i < rllList.size(); i++) {
        int finalI = i;
        //先全部隐藏
        rllList.get(finalI).setVisibility(View.GONE);
    }
}

private void itemsAnimation() {
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < rllList.size(); i++) {
                int finalI = i;
                //先全部隐藏
                rllList.get(finalI).setAlpha(0);
                rllList.get(finalI).setVisibility(View.VISIBLE);
            }
            for (int i = 0; i < rllList.size(); i++) {
                int finalI = i;
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        //设置透明度为全不透明
                        rllList.get(finalI).setAlpha(1);
                        //再执行动画
                        rllList.get(finalI).startAnimation(AnimationUtils.loadAnimation(BiaoDiscoverActivity.this, R.anim.grid\_items\_scale));
                    }
                }, 0 + i * 30);
            }
        }
    }, 200);

}

@Override
public void initListener() {
    super.initListener();
    mIvClose.setOnClickListener(v -> {
        finish();
        exitAct();
    });
    mrllClassroom.setOnClickListener(v -> jumpToWebViewActivity(AppConst.H5\_CLASSROOM\_SEARCH));
    mrllScore.setOnClickListener(v -> jumpToWebViewActivity(AppConst.H5\_SCORE\_RESULT_SEARCH));
    mrllSuperGroup.setOnClickListener(v -> jumpToWebViewActivity(AppConst.H5\_SUPER\_GROUP));
    mrllTrainTickets.setOnClickListener(v -> jumpToWebViewActivity(AppConst.H5\_TRAIN\_BUS_TICKETS));
    mrllSchoolRecuit.setOnClickListener(v -> jumpToWebViewActivity(AppConst.H5\_SCHOOL\_RECUIT));
    mrllAirTickets.setOnClickListener(v -> jumpToWebViewActivity(AppConst.H5\_AIR\_TICKETS));
    mrllHouseRent.setOnClickListener(v -> jumpToWebViewActivity(AppConst.H5\_HOUSE\_RENT));
    mrllEntertainment.setOnClickListener(v -> jumpToWebViewActivity(AppConst.H5\_ENTERTAINMANIT\_CLASS));
}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        finish();
        exitAct();
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

private void exitAct() {
    UIUtils.startWindowAnimation(this, R.anim.window\_as\_pop\_fade\_in, R.anim.window\_as\_pop\_fade\_out);
}

}

其父类为一个抽象类BaseActivity,子类中的各个重写方法在父类中的执行顺序如下

protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

    setContentView(provideContentViewId());
    ButterKnife.bind(this);

    initView();
    initListener();
    initData();

}

这样,只需在子类中重写provideContentViewId()方法,返回子类的content布局资源文件的值就可以了,子类不再需要设置布局ID,也不再需要每次调用ButterKnife.bind()

下面是重点

宫格布局的实现

以下是BiaoDiscoverActivity的布局资源文件

首先向 zhy 的 AutoLayout 表示感谢

这个宫格布局的实现方法不是唯一的,但以上实现方法可以保证95%以上的相似,以上用到的所有图标资源请自行搜索

下面是实现后的效果

需要注意的是,布局中的图标应避免处于父布局的边缘位置,因为执行动画过程中,尤其是缩放动画,超出父布局的部分不会显示

图标的缩放动画在同样在XML文件中进行定义,这里用到了两个缩放动画,可以设置第二个动画开始时间偏移量为第一个动画的时长,这样可以使最终效果非常自然、连贯,此处加入一个透明度渐变动画,和原版更为贴近

底部的关闭按钮用selector的形式定义,实现点击的效果

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.