ViewPager2 | View.ClickListener не вызывается
Я использую новый виджет Android ViewPager2 версии 1.0.0-alpha03, и когда я устанавливаю прослушиватель кликов, метод onClick() не вызывается.
Мой класс Actvity:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
supportFragmentManager.beginTransaction()
.add(R.id.fragmentContent, SecondFragment.newInstance(), SecondFragment.TAG)
.addToBackStack(SecondFragment.TAG)
.commit()
}
}
Мой фрагмент:
class SecondFragment : Fragment() {
companion object {
val TAG = SecondFragment::class.java.canonicalName
fun newInstance(): SecondFragment = SecondFragment()
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_second, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
viewPager2.setOnClickListener {
Log.d("logi", "click : ")
}
}
}
Мой макет XML-файла:
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager2"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Любое предположение или обходной путь?
3 ответа
Я нашел решение! ViewPager2 содержит RecyclerView, и мы должны работать с ним как RecyclerView. Я создаю RecyclerView.Adapter и устанавливаю ClickListener для itemView в конструктор RecyclerView.ViewHolder и VOILA!!!
во фрагменте:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
viewPager2.adapter = ViewPager2Adapter {
Log.d("logi", "clicked at : $it")
}
}
Адаптер RecyclerView:
class ViewPager2Adapter(private val itemClickListener: (Int) -> Unit) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
val items = mutableListOf<Any>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =
ItemViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item, parent, false))
override fun getItemCount(): Int = items.size
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
// bind your items
}
private inner class ItemViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
init {
itemView.setOnClickListener {
Log.d("logi", "Click!") // WORKS!!!
itemClickListener(adapterPosition)
}
}
}
}
Нет необходимости заходить внутрь RecyclerView или адаптера. ТолькоsetOnClickListener
на макете фрагмента штрафуется. Я просто использую этот метод.
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @NullableViewGroup container, @Nullable Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_config, container, false);
LinearLayout layout = view.findViewById(R.id.fragment_config_layout);
layout.setOnClickListener(c -> do_what_you_want());
return view;
}
Другой подход может быть таким, как показано ниже:
class MyAdapter(
private val items: List<Any>,
private val onItemClickListener: OnItemClickListener
) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val itemView = parent.inflate(R.layout.item_details_view_pager)
return MyViewHolder(itemView)
}
override fun getItemCount(): Int = items.size
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.imageView.apply {
setOnClickListener {
onItemClickListener.onItemClick(position)
}
...
}
}
inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val imageView: ImageView = itemView.findViewById(R.id.some_image_view)
}
}
Параметр конструктора onItemClickListener также может быть лямбдой, но для меня это простой интерфейс:
interface OnItemClickListener {
fun onItemClick(position: Int)
}