Android材质转换、片段和AppCompat

Android材质转换、片段和AppCompat,android,android-fragments,android-5.0-lollipop,transition,android-appcompat,Android,Android Fragments,Android 5.0 Lollipop,Transition,Android Appcompat,我正在尝试使用AppCompat库让所有棒棒糖共享转换成为可能。基本上,在一个活动中,有一个片段A,其中有一个recyclerview,每行有一些textview。当我点击这个recyclerview的一个项目时,我想启动片段B,将这个文本视图共享给片段B 我设法使它在两个活动之间工作,但有可能在两个片段之间实现共享转换吗?如果是这样的话,一个快速的提示/片段/样本(取决于你的威严)将非常感谢,因为我正在努力,但迄今为止没有成功 提前感谢。首先,记住使用活动、片段、片段管理器、任何转换和路径运动

我正在尝试使用AppCompat库让所有棒棒糖共享转换成为可能。基本上,在一个活动中,有一个片段A,其中有一个recyclerview,每行有一些textview。当我点击这个recyclerview的一个项目时,我想启动片段B,将这个文本视图共享给片段B

我设法使它在两个活动之间工作,但有可能在两个片段之间实现共享转换吗?如果是这样的话,一个快速的提示/片段/样本(取决于你的威严)将非常感谢,因为我正在努力,但迄今为止没有成功


提前感谢。

首先,记住使用
活动
片段
片段管理器
、任何
转换
路径运动
的支持版本

其次,我假设在主活动的布局文件中有一个ID为
container
的FrameLayout,您的共享TextView的ID为
mySharedTextView

在科特林:

您的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")
            }
        }

        ...
    }

}
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)}")

    }

}
就这些了