android windowistranslucent 转场动画,android recyclerview点击跳转到viewpager共享元素动画...

今天做项目的时候用到了Transition动画。也就是android5.0中出现的。基本的使用方式我们都知道是用TransitionName在两个activity中进行绑定。现在的场景是activityA中有个recyclerview,点击item的时候跳转到activityB。B中是一个类似全屏的viewpager。item中的图片元素共享的viewpager指定的Item上。并且viewpager可以动态删除item,返回的A的时候item也要同步数量。

想想实现功能应该不难。难的地方在于两个页面的item数量不一样,共享元素view的位置可能也不一样。如果B当中已经改变了item的数量和选中的viewpager的position的位置,A那边的共享元素该如何改变呢。现在开始展现真正的轮子了。

1、基本使用

设置两个activity的style中 android:windowContentTransitions 为true

false

true

true

false

true

共享元素关键点是绑定的view和view的TransitionName,那么我们就要给itemView设置transitionName了。这里我们使用url给item设置TransitionName,如果item的url一样那么可以自己想想,保持唯一就行了。

ViewCompat.setTransitionName(holder.itemView, ims.get(position).url);

ViewCompat是support兼容类。不然就要写一堆判断了很是烦。

启动activity绑定transitionView,将list和选中的item传入

ActivityOptionsCompat options =

ActivityOptionsCompat.makeSceneTransitionAnimation(A.this,

holder.itemView, ViewCompat.getTransitionName(holder.itemView));

Intent intent = new Intent(A.this, B.class);

intent.putExtra(B.INTENT_SELECT_POSITION, imgs.get(holder.getAdapterPosition()));

intent.putParcelableArrayListExtra(B.INTENT_IMGS, imgs);

ActivityCompat.startActivityForResult(A.this, intent, REQUEST_CODE_PREVIEW, options.toBundle());

之后我们到了B的Activity,这里我们不要为viewpager的每个itemview设置transitionName,我们直接给viewpager设置transitionName,以为viewpager选中页的两边都会加载view,处理起来稍微有点麻烦,直接设置viewpager的transitionName反而方便连贯。

//currentItem是我从上个页面传进来的Item

ViewCompat.setTransitionName(viewPager, currentItem.url);

....

//设置选中的item

viewPager.setCurrentItem(i);

@Override

public void onBackPressed() {

checkFinish(RESULT_OK);

}

/**

* 通过转场动画finish

*/

private void checkFinish(int resultCode) {

Intent intent = new Intent();

intent.putParcelableArrayListExtra(INTENT_IMGS, imgs);

setResult(resultCode, intent);

supportFinishAfterTransition();

}

2、进阶使用

基本的点击返回效果我们就搞好了,可是还是会出现动画不连贯的效果。一头雾水的搜了一下

//如果共享元素需要通过AsyncTask,一个Loader,或其他类似的进行数据加载在被调用的

//Activity决定它们最终的表现,数据被分发返回到主线程之前框架可以开始过渡。

supportPostponeEnterTransition()//暂时阻止共享元素过渡

supportStartPostponedEnterTransition//确认元素都已经摆放完成恢复过度

因为viewpager.setCurrentItem之后UI毕竟是在默认300ms完成绘制。所以我们要等待viewpager完全展示完成才能进行过渡动画的渲染。

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

supportPostponeEnterTransition();

....//更新ui

//监听viewpager布局树已经绘制完成

viewPager.getViewTreeObserver().addOnGlobalLayoutListener(new

ViewTreeObserver.OnGlobalLayoutListener() {

@Override

public void onGlobalLayout() {

viewPager.getViewTreeObserver().removeOnGlobalLayoutListener(this);

//释放

supportStartPostponedEnterTransition();

}

});

}

这样我们的连贯效果就实现了。

3、完成实现

因为我们知道B页面是带有删除和翻页功能的,所以我们就要进行页面之间切换时候的ui数据整理。我试着在onActivityResult中用supportPostponeEnterTransition和supportStartPostponedEnterTransition实现数据的变换,发现效果并没有实现,onActivityResult在过渡动画后才调用。所以还是搜索一下

/**

* Called when an activity you launched with an activity transition exposes this

* Activity through a returning activity transition, giving you the resultCode

* and any additional data from it. This method will only be called if the activity

* set a result code other than {@link #RESULT_CANCELED} and it supports activity

* transitions with {@link Window#FEATURE_ACTIVITY_TRANSITIONS}.

*

*

The purpose of this function is to let the called Activity send a hint about

* its state so that this underlying Activity can prepare to be exposed. A call to

* this method does not guarantee that the called Activity has or will be exiting soon.

* It only indicates that it will expose this Activity's Window and it has

* some data to pass to prepare it.

*

* @param resultCode The integer result code returned by the child activity

* through its setResult().

* @param data An Intent, which can return result data to the caller

* (various data can be attached to Intent "extras").

*/

public void onActivityReenter(int resultCode, Intent data) {

//当你使用了过度动画返回时候就会调用此方法,通过supportPostponeEnterTransition和supportStartPostponedEnterTransition可以延缓动画的发生

//只要resultCode不是RESULT_CANCELED并且 Window#FEATURE_ACTIVITY_TRANSITIONS这个已经在theme里设置了

}

@Override

public void onActivityReenter(int resultCode, Intent data) {

if (resultCode == RESULT_OK && data != null) {

//针对classloader回收 我这里出现了这个问题,如果没有请忽略

data.setExtrasClassLoader(getClass().getClassLoader());

ArrayList limgs = data.getParcelableArrayListExtra(B.INTENT_IMGS);

imgs = limgs;

adapter.setIms(imgs);

adapter.notifyDataSetChanged();

supportPostponeEnterTransition();

binding.recyclerview.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

@Override

public void onGlobalLayout() {

recyclerview.getViewTreeObserver().removeOnGlobalLayoutListener(this);

supportStartPostponedEnterTransition();

}

});

}

super.onActivityReenter(resultCode, data);

}

满怀希望的试一试。结果懵逼,切换了还是没效果。。。==。B页面的共享viewpager的TransitionName还是原来的。我们要在返回的时候设置viewpager的TransitionName为当前选中的item的url。

B中

/**

* 通过转场动画finish

*/

private void checkFinish(int resultCode) {

Intent intent = new Intent();

setEnterShareCallback(currentItem);

intent.putParcelableArrayListExtra(INTENT_IMGS, imgs);

setResult(resultCode, intent);

supportFinishAfterTransition();

}

private void setEnterShareCallback(String url) {

//设置共享元素们的回调

setEnterSharedElementCallback(new SharedElementCallback() {

@Override

public void onMapSharedElements(List names, Map sharedElements) {

sharedElements.clear();

names.clear();

if (currentItem==null){

return;

}

names.add(url);

sharedElements.put(url,viewPager);

}

});

}

哈哈 。可以了。不过最后一步中,感觉只需要设置viewpager的TransitionName就行了,没试过。有时间再试试吧。

4、遇到的问题

项目加载网络图片会出现一些问题。如果使用glide的话要禁用动画加载dontAnimate。

还有部分时候会出现viewpager翻页会出现返回动画失效的问题,我们在返回的时候需要进行view的替换

@Override

protected void onCreate(Bundle savedInstanceState) {

setExitSharedElementCallback(new SharedElementCallback() {

@Override

public void onMapSharedElements(List names, Map sharedElements) {

//isBack为成员变量 如果启动B页面设置为false,onActivityReenter后为true

if (isBack) {

names.clear();

names.add(shareName);

sharedElements.clear();

sharedElements.put(shareName, shareView);

}

}

});

}

public void onActivityReenter(){

//更新adapter

.......

recyclerview.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

@Override

public void onGlobalLayout() {

notifyCallView(data);

recyclerview.getViewTreeObserver().removeOnGlobalLayoutListener(this);

supportStartPostponedEnterTransition();

}

});

}

private void notifyCallView(Intent data) {

//遍历recyclerview.getchildCount 从B页面返回的url值

.....

shareName = url;

shareView = viewHolder.itemView;

}

over

点击数:735

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值