Demo-RecyclerViewEnterAnimation
Demo-RecyclerViewEnterAnimation copied to clipboard
Grid animation is not working with data binding
You can watch this video Here is my code and animation resources are the exactly same as yours
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val binding = DataBindingUtil.inflate<FragmentMovieListBinding>(inflater, R.layout.fragment_movie_list, container, false)
initRecyclerView(binding)
val model = ViewModelProviders.of(this).get(MovieListViewModel::class.java)
model.listType = listType
binding.viewModel = model
getMovieList(binding)
return binding.root
}
private fun getMovieList(binding: FragmentMovieListBinding) {
binding.viewModel.getMovieList()
.subscribe({ movieResponse ->
movieResponse.results.let {
adapter.setMovieList(it)
val animation = AnimationUtils.loadLayoutAnimation(activity, R.anim.grid_layout_animation_from_bottom)
binding.listRecyclerView.layoutAnimation = animation
binding.listRecyclerView.adapter.notifyDataSetChanged()
binding.listRecyclerView.scheduleLayoutAnimation()
}
}, { throwable ->
Timber.e(throwable)
})
}
private fun initRecyclerView(binding: FragmentMovieListBinding) {
val manager = GridLayoutManager(activity, 3)
binding.listRecyclerView.layoutManager = manager
binding.listRecyclerView.adapter = adapter
}
class AdvancedRecyclerView : RecyclerView {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle)
override fun attachLayoutAnimationParameters(child: View, params: ViewGroup.LayoutParams,
index: Int, count: Int) {
val layoutManager = layoutManager
if (adapter != null && layoutManager is GridLayoutManager) {
var animationParams: GridLayoutAnimationController.AnimationParameters? = null
if (params.layoutAnimationParameters == null) {
// If there are no animation parameters, create new once and attach them to
// the LayoutParams.
animationParams = GridLayoutAnimationController.AnimationParameters()
params.layoutAnimationParameters = animationParams
}
// Next we are updating the parameters
// Set the number of items in the RecyclerView and the index of this item
animationParams?.count = count
animationParams?.index = index
// Calculate the number of columns and rows in the grid
val columns = layoutManager.spanCount
animationParams?.columnsCount = columns
animationParams?.rowsCount = count / columns
// Calculate the column/row position in the grid
val invertedIndex = count - 1 - index
animationParams?.column = columns - 1 - invertedIndex % columns
animationParams?.row = animationParams!!.rowsCount - 1 - invertedIndex / columns
} else {
// Proceed as normal if using another type of LayoutManager
super.attachLayoutAnimationParameters(child, params, index, count)
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="viewModel"
type="com.dtunctuncer.todomovielist.ui.discover.movielist.MovieListViewModel" />
</data>
<com.dtunctuncer.todomovielist.core.widgets.AdvancedRecyclerView
android:id="@+id/listRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutAnimation="@anim/grid_layout_animation_from_bottom" />
</layout>
The one time I ran into something similar it was due to me setting the item view visibility to GONE instead of INVISIBLE at the start, causing the item to not being measured properly and the animation to fail. Perhaps you have some similar scenario in onBindViewHolder in the adapter?
Sorry I do not change any visibility in my code.
class MovieListAdapter(val application: Application) : RecyclerView.Adapter<MovieListAdapter.ViewHolder>() {
private var movieList: List<Movie?>? = null
init {
movieList = emptyList()
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.binding.viewModel.setMovie(movieList?.get(position))
}
override fun getItemCount(): Int = movieList?.size ?: 0
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = DataBindingUtil.inflate<ItemMovieListBinding>(LayoutInflater.from(parent.context), R.layout.item_movie_list, parent, false)
val viewModel = MovieListAdapterViewModel(application)
binding.viewModel = viewModel
return ViewHolder(binding)
}
fun setMovieList(movieList: List<Movie?>?) {
this.movieList = movieList
notifyDataSetChanged()
}
class ViewHolder(val binding: ItemMovieListBinding) : RecyclerView.ViewHolder(binding.root)
}
class MovieListAdapterViewModel(val app: Application) : AndroidViewModel(app) {
var movie: ObservableField<Movie> = ObservableField()
var picture: ObservableField<Drawable> = ObservableField()
var statusPicture: ObservableField<Drawable> = ObservableField()
private var bindableFieldTarget: BindableFieldTarget? = null
fun setMovie(movie: Movie?) {
bindableFieldTarget = BindableFieldTarget(picture, app.resources, statusPicture)
Picasso.with(app).load(BuildConfig.SMALL_IMAGE_URL + movie?.posterPath).placeholder(R.drawable.animation_progress).error(R.drawable.error).into(bindableFieldTarget)
this.movie.set(movie)
}
fun onClick() {
val intent = Intent(app, MovieActivity::class.java)
intent.putExtra(MovieActivity.ARG_MOVIE, movie.get())
app.startActivity(intent)
}
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="viewModel"
type="com.dtunctuncer.todomovielist.ui.discover.movielist.MovieListAdapterViewModel" />
</data>
<com.dtunctuncer.todomovielist.core.widgets.RectangleLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="2dp"
android:onClick="@{() -> viewModel.onClick()}">
<ImageView
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_gravity="center"
android:src="@{viewModel.statusPicture}" />
<ImageView
android:id="@+id/posterImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@{viewModel.picture}"
android:transitionName="@string/poster_image_trasition_name" />
</com.dtunctuncer.todomovielist.core.widgets.RectangleLayout>
</layout>
Is the issue just when using Grids? What happens if you switch to a LinearLayoutManager and the regular RecyclerView?
I've never used the Data Binding apis so not sure how/if they might have an effect on the LayoutAnimation.
Sorry for late answer no I haven't tryed it with LinearLayoutManager I think problem is Data Binding