我正在2个活动(RecyclerView
和MainActivity
)的2个DetailActivity
项目之间使用默认的共享元素过渡。从MainActivity
到DetailActivity
的动画效果很好,但是如果用户已滚动到DetailActivity
中的新项目,则重新输入动画会将项目移到顶部。我根据需要修改了Android Developers Blog上共享的示例。这是我的代码中的Github Link。我还尝试过在DetailActivity
上禁用退出动画,并尝试将退出动画更改为仅淡入淡出,但这几乎就像完全不尊重退出动画一样。
这是一个视频演示(问题可以在最近几秒钟内看到):
MainActivity:
class MainActivity : AppCompatActivity(), ListImageAdapter.ListImageClickListener {
private lateinit var imageData: ImageData
private lateinit var listImageAdapter: ListImageAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupGallery()
prepareTransitions()
}
@SuppressLint("RestrictedApi")
override fun onListImageClick(position: Int, imageView: ImageView) {
val intent = Intent(this, DetailActivity::class.java)
intent.putExtra("IMAGE_DATA", imageData)
val activityOptions = ActivityOptions.makeSceneTransitionAnimation(this, imageView,
ViewCompat.getTransitionName(imageView))
startActivityForResult(intent, 101, activityOptions.toBundle())
}
override fun onActivityReenter(resultCode: Int, data: Intent?) {
data?.let { intent ->
if (intent.hasExtra("IMAGE_DATA")) {
imageData = intent.getParcelableExtra("IMAGE_DATA")
listImageAdapter.images = imageData.images
val position = imageData.images.indexOfFirst { it.selected }
itemGallery.scrollToPosition(position)
}
}
super.onActivityReenter(resultCode, data)
}
private fun setupGallery() {
imageData = ImageData(getGalleryItems())
val snapHelper = PagerSnapHelper()
snapHelper.attachToRecyclerView(itemGallery)
listImageAdapter = ListImageAdapter(imageData.images, this)
itemGallery.adapter = listImageAdapter
itemGallery.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
val selectedView = snapHelper.findSnapView(itemGallery.layoutManager)
selectedView?.let {
val selectedPosition = itemGallery.layoutManager?.getPosition(selectedView)
selectedPosition?.let { onMediumGalleryItemHighlighted(selectedPosition) }
}
}
}
})
}
private fun onMediumGalleryItemHighlighted(position: Int) {
imageData.images = imageData.images.mapIndexed { index, galleryItem ->
when {
index == position -> galleryItem.copy(selected = true)
galleryItem.selected -> galleryItem.copy(selected = false)
else -> galleryItem
}
}
}
private fun prepareTransitions() {
setExitSharedElementCallback(
object : SharedElementCallback() {
override fun onMapSharedElements(names: List<String>?, sharedElements: MutableMap<String, View>?) {
val selectedPosition = imageData.images.indexOfFirst { it.selected }
val selectedViewHolder = itemGallery
.findViewHolderForAdapterPosition(selectedPosition)
if (selectedViewHolder?.itemView == null) {
return
}
sharedElements!![names!![0]] = selectedViewHolder.itemView.findViewById(R.id.listItemImage)
}
})
}
private fun getGalleryItems(): List<Image> {
return listOf(
Image(R.drawable.cat, true),
Image(R.drawable.lion, false),
Image(R.drawable.tortoise, false)
)
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="false"
>
<View android:id="@+id/otherContent"
android:layout_width="match_parent"
android:layout_height="256dp"
android:background="@android:color/holo_green_light"
/>
<android.support.v7.widget.RecyclerView
android:id="@+id/itemGallery"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:layout_below="@+id/otherContent"
app:layoutManager="android.support.v7.widget.LinearLayoutManager" />
</RelativeLayout>
DetailActivity:
class DetailActivity : AppCompatActivity() {
private lateinit var detailImageAdapter: DetailImageAdapter
private lateinit var imageData: ImageData
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_detail)
imageData = intent.extras.getParcelable("IMAGE_DATA")
initViews()
prepareTransitions()
resetScrolledPosition()
}
private fun initViews() {
val snapHelper = PagerSnapHelper()
snapHelper.attachToRecyclerView(detailGallery)
detailImageAdapter = DetailImageAdapter(imageData.images)
detailGallery.adapter = detailImageAdapter
detailGallery.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
val selectedView = snapHelper.findSnapView(detailGallery.layoutManager)
selectedView?.let {
val selectedPosition = detailGallery.layoutManager?.getPosition(selectedView)
selectedPosition?.let { onItemSelected(selectedPosition) }
}
}
}
})
}
private fun resetScrolledPosition() {
val position = imageData.images.indexOfFirst { it.selected }
imageData.images = imageData.images.mapIndexed { index, galleryItem ->
when {
index == position -> {
galleryItem.copy(selected = true)
}
galleryItem.selected -> galleryItem.copy(selected = false)
else -> galleryItem
}
}
detailImageAdapter.images = imageData.images
detailGallery.scrollToPosition(position)
supportStartPostponedEnterTransition()
}
private fun onItemSelected(position: Int) {
imageData.images = imageData.images.mapIndexed { index, galleryItem ->
when {
index == position -> galleryItem.copy(selected = true)
galleryItem.selected -> galleryItem.copy(selected = false)
else -> galleryItem
}
}
}
override fun onBackPressed() {
var resultIntent = Intent()
resultIntent = resultIntent.putExtra("IMAGE_DATA", imageData)
setResult(Activity.RESULT_OK, resultIntent)
super.onBackPressed()
}
private fun prepareTransitions() {
setEnterSharedElementCallback(
object : SharedElementCallback() {
override fun onMapSharedElements(names: List<String>?, sharedElements: MutableMap<String, View>?) {
val selectedPosition = imageData.images.indexOfFirst { it.selected }
val selectedViewHolder = detailGallery.findViewHolderForAdapterPosition(selectedPosition)
if (selectedViewHolder?.itemView == null) {
return
}
sharedElements!![names!![0]] = selectedViewHolder.itemView.findViewById(R.id.detailItemImage)
}
})
}
}
activity_detail.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
android:animateLayoutChanges="false"
>
<android.support.v7.widget.RecyclerView
android:id="@+id/detailGallery"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
app:layoutManager="android.support.v7.widget.LinearLayoutManager" />
</FrameLayout>
答案 0 :(得分:1)
请检查GithubLink上的共享元素转换代码
SharedElementTransition-master.zip 是源代码中的更新代码,其中Transition在两个RecyclerView之间起作用。
android-gallery-master.zip 是RecyclerView和ViewPager之间过渡的另一代码。
希望它会为您工作。我将尽快添加解释。