我在片段 A 中创建了一个回收器视图,单击一个元素时它会打开第二个片段,从一个 oage 到另一个 oage 的图像应该动画化。进入动画工作正常,但退出动画不起作用。片段是使用导航编辑器添加的。
这是代码:
回收商查看片段 ->
public class SightSeeingFragment extends Fragment {
RecyclerView sightSeeingRv;
ArrayList<Place> placeArrayList;
SightSeeingAdapter sightSeeingAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
postponeEnterTransition();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_sight_seeing, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
postponeEnterTransition();
init(view);
}
private void init(View view) {
sightSeeingRv = view.findViewById(R.id.sight_seeing_rv);
setRecyclerView();
}
private void setRecyclerView() {
new SetRecyclerView().execute();
}
class SetRecyclerView extends AsyncTask<Void, Void, Void> {
@Override
protected void onPreExecute() {
super.onPreExecute();
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
sightSeeingRv.setLayoutManager(linearLayoutManager);
}
@Override
protected Void doInBackground(Void... voids) {
placeArrayList = new Gson().fromJson(placesToVisit,
new TypeToken<List<Place>>() {
}.getType());
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if (sightSeeingAdapter == null)
sightSeeingAdapter = new SightSeeingAdapter(getContext(), placeArrayList);
sightSeeingRv.setAdapter(sightSeeingAdapter);
sightSeeingRv.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
startPostponedEnterTransition();
return true;
}
});
}
}
}
适配器 ->
public class SightSeeingAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
Context context;
ArrayList<Place> placeArrayList;
public SightSeeingAdapter(Context context, ArrayList<Place> placeArrayList) {
this.context = context;
this.placeArrayList = placeArrayList;
if(this.placeArrayList == null)
placeArrayList = new ArrayList<>();
}
@Override
public int getItemViewType(int position) {
if(position == 0)
return 0;
else return 1;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if(viewType == 0)
{
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.sightseeing_row_0, parent, false);
return new SightSeeingTextViewHolder(view);
}else
{
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.row_sight_seeing, parent, false);
return new SightSeeingViewHolder(view);
}}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if(position!=0) {
((SightSeeingViewHolder)holder).bindView(position-1);
}
}
@Override
public int getItemCount() {
return placeArrayList.size()+1;
}
class SightSeeingTextViewHolder extends RecyclerView.ViewHolder {
public SightSeeingTextViewHolder(@NonNull View itemView) {
super(itemView);
}
}
class SightSeeingViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView nameOfPlace;
TextView descOfPlace;
ImageView imageOfPlace;
CardView placeRow;
int position;
public SightSeeingViewHolder(@NonNull View itemView) {
super(itemView);
nameOfPlace = itemView.findViewById(R.id.name_of_place);
descOfPlace = itemView.findViewById(R.id.desc_of_place);
imageOfPlace = itemView.findViewById(R.id.image_of_place);
placeRow = itemView.findViewById(R.id.place_row);
}
public void bindView(int position) {
Place place = placeArrayList.get(position);
this.position = position;
nameOfPlace.setText(place.getNameOfPlace());
descOfPlace.setText(place.getShortDescription());
placeRow.setTag(position);
placeRow.setOnClickListener(this);
Glide.with(context).load(Utils.getDrawableImage(place.getImage(),context)).into(imageOfPlace);
ViewCompat.setTransitionName(imageOfPlace, position+"");
}
@Override
public void onClick(View view) {
int position = (int) view.getTag();
FragmentNavigator.Extras extras = new FragmentNavigator.Extras.Builder()
.addSharedElement(imageOfPlace,position+"").build();
Navigation.findNavController(view)
.navigate(SightSeeingFragmentDirections.actionNavigationSightseeingToPlaceholder()
.setPlaceDetail(placeArrayList.get(position)).setTransitionName(position+""),extras);
}
}
}
片段 B ->
public class DetailOfPlaceFragment extends Fragment implements View.OnClickListener {
Place place;
ImageView placeImage;
TextView placeDetails;
Button checkTheLocation;
String transitionName;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
postponeEnterTransition();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
setSharedElementEnterTransition(TransitionInflater.from(getContext()).inflateTransition(android.R.transition.move));
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_detail_of_place, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
place = DetailOfPlaceFragmentArgs.fromBundle(getArguments()).getPlaceDetail();
transitionName = DetailOfPlaceFragmentArgs.fromBundle(getArguments()).getTransitionName();
init(view);
}
private void init(View view) {
placeImage = view.findViewById(R.id.place_image);
placeDetails = view.findViewById(R.id.place_details);
checkTheLocation = view.findViewById(R.id.check_the_location);
checkTheLocation.setOnClickListener(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
placeImage.setTransitionName(transitionName);
}
Glide.with(getContext()).load(Utils.getDrawableImage(place.getImage(),getContext())).listener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
startPostponedEnterTransition();
return false;
}
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
startPostponedEnterTransition();
return false;
}
}).into(placeImage);
placeDetails.setText(place.getDescription());
}
@Override
public void onClick(View view) {
String url = String.format(getString(R.string.maps_url),place.getLatOnMap()+"",
place.getLondOnMap()+"",place.getNameOfPlace());
Utils.openActionIntent(url,getContext());
}
}
此外,由于动画推迟,输入动画没有太多流畅。但这是次要问题。
您的 RecyclerView 片段还需要使用postponeEnterTransition()
和startPostponedEnterTransition()
:当它被放在后退堆栈上时,它的视图将被销毁,并且在不推迟转换的情况下,共享元素转换将尝试在您的AsyncTask
实际完成之前发生,RecyclerView
被重新填充数据,导致没有视图可以返回。
将共享元素转换添加到 GithubBrowserSample 的拉取请求是查找需要更改的所有移动部分的好起点。