安卓材料设计过渡、碎片和AppCompat

3
我正在尝试使用AppCompat库来实现所有Lollipop共享过渡。基本上,在一个活动中,有一个带有recyclerview的A片段,每行都有一些textview。当我点击这个recyclerview的项目时,我想启动片段B并与该文本视图共享到片段B中。
如果在两个活动之间进行,则可以使其正常工作,但是是否可以在两个片段之间实现共享转换?如果可以的话,希望您能给出快速提示/片段/示例(取决于您的精彩),因为我一直在努力但迄今没有成功!
谢谢你的提前回复。
1个回答

0
首先,记得为 ActivityFragmentFragmentManager、任何 TransitionPathMotion 使用支持版本。
其次,我假设在主活动的布局文件中有一个 ID 为 container 的 FrameLayout,并且您共享的 TextView 具有 ID mySharedTextView
在 Kotlin 中:
您的 MainActivity.kt:
class MainActivity : AppCompatActivity(),
        FirstFragment.OnItemSelectedListener {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.main)
        supportFragmentManager.beginTransaction()
                        .replace(R.id.container, FirstFragment.newInstance())
                        .addToBackStack(null)
                        .commit()
    }

    // The listener implementation from the first fragment
    override fun onItemSelected(id: Long, view: View) {

        // The second fragment
        val secondFragment = SecondFragment.newInstance(itemId)

        // Shared elements transition (always on the second fragment). These transitions are examples and for the TextView you will probably want some others. You can also inflate the transition from xml file with TransitionInflator, but again the transitions has to be from support library or made by yourself.
        val sharedElementTransition = TransitionSet()
        val changeBounds = ChangeBounds()
        changeBounds.setPathMotion(ArcMotion())
        sharedElementTransition
                .addTransition(changeBounds)
                .addTransition(ChangeTransform())
                .addTransition(ChangeClipBounds())
                .addTransition(ChangeImageTransform())
        secondFragment.sharedElementEnterTransition = sharedElementTransition
        secondFragment.sharedElementReturnTransition = sharedElementTransition

        // A simple fade animation for the rest of the views (always on the second fragment)
        val mainTransition =  Fade()
        secondFragment.enterTransition = mainTransition
        secondFragment.exitTransition = mainTransition

        // Do the replacement
        supportFragmentManager.beginTransaction()
                .addSharedElement(view, "${SecondFragment.SHARED_TRANSITION_NAME}-$itemId") // Add the share element with the transition ID
                .replace(R.id.container, secondFragment)
                .addToBackStack(null)
                .commit()
    }
}

你的FirstFragment.kt文件:

class FirstFragment : Fragment() {
    companion object {
        @JvmStatic
        fun newInstance() = FirstFragment()
    }

    // A listener so we can comunicate with MainActivity
    private lateinit var listener: OnItemSelectedListener

    interface OnItemSelectedListener {
        fun onAdSelected(adId: Long, view: View)
    }

    // We use the MainActivity as listener. If activity do not implement the listener interface (OnItemSelectedListener), an error is going to be thrown
    override fun onAttach(context: Context) {
        super.onAttach(context)
        try {
            listener = activity as OnItemSelectedListener
        } catch (e: ClassCastException) {
            throw ClassCastException("${activity!!.javaClass} must implement OnItemSelectedListener")
        }
    }

   ... onCreate, onCreateView, etc...

   inner class ItemAdapter(var items: List<Item> = emptyList()) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

        ...

        override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
            when (holder) {
                is ItemViewHolder -> holder.bind(items[position].id)
            }
        }

        internal inner class AdViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

            fun bind(itemId: Long) {

                // Set the onClickListener to call the listener method that should be implemented by MainActivity
                itemView.setOnClickListener {
                    listener.onItemSelected(itemId, itemView.mySharedTextView)
                }

                // Give the shared element in this first fragment the same transition ID it will have on the second. They need to be unique, so we are appending the item ID to it. They also HAS to be set on the bind instead of onCrateViewHolder, otherwise when your RecyclerView is using a recycled view it will have the wrong item ID on the transition name.
                ViewCompat.setTransitionName(itemView.mySharedTextView, "${SecondFragment.SHARED_TRANSITION_NAME}-$itemId")
            }
        }

        ...
    }

}

你的 SecondFragment.kt 文件:

class SecondFragment : Fragment() {
    companion object {
        const val ARG_ITEM_ID = "ARG_ITEM_ID"

        const val SHARED_TRANSITION_NAME = "text_view_transition_name"

        @JvmStatic
        fun newInstance(itemId: Long): SecondFragment {
            val fragment = SecondFragment()
            fragment.arguments = Bundle()
            fragment.arguments!!.putLong(ARG_ITEM_ID, itemID)
            return fragment
        }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {

        // Inflate the layout
        val view = inflater.inflate(R.layout.second_fragment, container, false)

        // Give the shared view on the second/detail fragment the same transition ID from the first
        ViewCompat.setTransitionName(view.mySharedTextView, "$SHARED_TRANSITION_NAME-${arguments!!.getLong(ARG_ITEM_ID)}")

    }

}

就是这样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接