@Kogoth

Как обратиться к ViewPager из динамически назначенного Fragment?

Имеется fragment_shop.xml:
spoiler
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".FunBoxStore">

    <android.support.v4.view.ViewPager
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

</android.support.design.widget.CoordinatorLayout>

Для него создан класс Shop_fragment.kt:
spoiler
class Shop_fragment : Fragment() {
    val TAG = "Shop"
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_shop, null)
    }
}

Так же есть основное окно activity_fun_box_store.xml где кнопки должны сменять фрагменты:
spoiler
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".FunBoxStore">

    <LinearLayout
        android:id="@+id/active_fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:layout_above="@id/switch_for_fragment" />

    <LinearLayout
        android:id="@+id/switch_for_fragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_alignParentBottom="true">

        <Button
            android:id="@+id/shop_btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/shop_btn" />

        <Button
            android:id="@+id/store_btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/store_btn" />

    </LinearLayout>
</RelativeLayout>

И наконец исходный код:
spoiler
class FunBoxStore : AppCompatActivity() {

    private val shop_fragment: Shop_fragment = Shop_fragment()
    private val store_fragment: Store_fragment = Store_fragment()
    private var manager: FragmentManager? = null
    private var transaction: FragmentTransaction? = null
    private var mSectionsPagerAdapter: SectionsPagerAdapter? = null
    private val products = ArrayList<Product>()
    private val products_showed = ArrayList<Product>()
    private val blank_product = Product("Товаров больше нет",0f,0)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_fun_box_store)

        manager=supportFragmentManager
        transaction = manager?.beginTransaction()
        transaction?.add(R.id.active_fragment,shop_fragment,shop_fragment.TAG)
        transaction?.commit()

        shop_btn.setOnClickListener{
            transaction = manager?.beginTransaction()
            transaction?.replace(R.id.active_fragment,shop_fragment,shop_fragment.TAG)
            transaction?.commit()
        }

        mSectionsPagerAdapter = SectionsPagerAdapter(supportFragmentManager)

        //Попытка установить adapter через findViewById

        //val viewPager = findViewById<ViewPager>(R.id.container)
        //viewPager.adapter = mSectionsPagerAdapter

        //Попытка установить adapter через findFragmentByTag (в if не входит без него виснет)

        /*if(manager?.findFragmentByTag(shop_fragment.TAG) is Shop_fragment){
            (manager?.findFragmentByTag(shop_fragment.TAG) as Shop_fragment).container.adapter = mSectionsPagerAdapter
            Log.d("myLogs", "нашелся")
        }*/

        //Попытка установить adapter через прямое обращение к экземпляру класса

        //shop_fragment.container.adapter = mSectionsPagerAdapter

        //Способ напрямую без фрагментов работает если ViewPager разместить на activity_fun_box_store.xml

        //container.adapter = mSectionsPagerAdapter

        products.add(Product("Apple iPod touch 5 32Gb", 8888f, 5))
        products.add(Product("Samsung Galaxy S Duos S7562", 7230f, 5))
        products.add(Product("Canon EOS 600D Kit", 15659f, 0))

        for (product in products) {
            if (product.merch_amt>0) {
                products_showed.add(product)
            }
        }

        //Попытка обратиться к adapter через findViewById

        //viewPager.adapter?.notifyDataSetChanged()

        //Попытка обратиться к adapter через findFragmentByTag (в if не входит без него виснет)

        /*if(manager?.findFragmentByTag(shop_fragment.TAG) is Shop_fragment){
            (manager?.findFragmentByTag(shop_fragment.TAG) as Shop_fragment).container.adapter?.notifyDataSetChanged()
            Log.d("myLogs", "нашелся")
        }*/

        //Попытка обратиться к adapter через прямое обращение к экземпляру класса

        //shop_fragment.container.adapter?.notifyDataSetChanged()

        //Способ напрямую без фрагментов работает если ViewPager разместить на activity_fun_box_store.xml

        //container.adapter = mSectionsPagerAdapter
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        // Inflate the menu; this adds items to the action bar if it is present.
        menuInflater.inflate(R.menu.menu_fun_box_store, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        val id = item.itemId
        if (id == R.id.action_settings) {
            return true
        }
        return super.onOptionsItemSelected(item)
    }

    inner class SectionsPagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm) {

        override fun getItem(position: Int): Fragment {
            return if (products_showed.size > 0) {
                PlaceholderFragment.newInstance(position + 1, products_showed[position])
            }else{
                PlaceholderFragment.newInstance(position+1,blank_product)
            }
        }

        override fun getCount(): Int {
            Log.d("myLogs", "fuck"+products_showed.size.toString())
            return if (products_showed.size > 0) {
                products_showed.size
            }else{
                1
            }
        }
    }

    class PlaceholderFragment : Fragment() {

        override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                                  savedInstanceState: Bundle?): View? {
            val rootView = inflater.inflate(R.layout.fragment_fun_box_store, container, false)
            rootView.name.text =  arguments?.getString("MERCH_NAME")
            rootView.price.text =  arguments?.getFloat("MERCH_PRICE").toString()
            rootView.amt.text =  arguments?.getInt("MERCH_AMT").toString()
                    //getString(R.string.section_format, arguments?.getInt(ARG_SECTION_NUMBER))
            return rootView
        }

        companion object {

            private val ARG_SECTION_NUMBER = "section_number"

            fun newInstance(sectionNumber: Int, product:Product): PlaceholderFragment {
                val fragment = PlaceholderFragment()
                val args = Bundle()
                args.putInt(ARG_SECTION_NUMBER, sectionNumber)
                args.putString("MERCH_NAME",product.merch_name)
                args.putFloat("MERCH_PRICE",product.merch_price)
                args.putInt("MERCH_AMT",product.merch_amt)
                fragment.arguments = args
                return fragment
            }
        }
    }
}

Ну и собственно вопрос - как же всетаки обратиться к ViewPager с android:id="@+id/container" который был создан в private val shop_fragment: Shop_fragment = Shop_fragment() из inflater.inflate(R.layout.fragment_shop, null) и назначен во фаргмент active_fragment с помощью transaction?.add(R.id.active_fragment,shop_fragment,shop_fragment.TAG)???
  • Вопрос задан
  • 276 просмотров
Решения вопроса 1
@Kogoth Автор вопроса
БОООЖЕ МОЙ!! ДАЙТЕ МНЕ МОЛОТОК И ГОЛОВУ ТОГО КТО ЭТО ПРИДУМАЛ!!!!!!!
Оказывается transaction?.commit() не выполняется сразу!!!! эта тварь может быстро сработать а может хз сколько ждать! В итоге чтобы гарантированно обратиться к элементам фрагмента надо перед этим выполнить manager?.executePendingTransactions() чтобы насильно закоммитить транзакцию! Это же просто противоречит самому смыслу транзакций!!! ААА

------------------------------------------------------------------------------------------------------------------------------------------

Прошёл миллион лет... Я понял что транзакция выполняется в отдельном потоке, и все обращения к элементам фрагмента надо делать в его собственном методе onCreate(). ))))
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
zagayevskiy
@zagayevskiy Куратор тега Android
Android developer at Yandex
Во-первых, фрагмент должен быть вещью в себе, никто не должен знать, какие у него внутри вьюхи, он инкапсулирует их в себе.
Во-вторых, когда фрагмент создан, это ещё ничего не значит. Весь его жизненный цикл начинается только после добавления в менеджер фрагментов. Соответственно, к вьюхам можно обращаться только после выполнения onCreateView. И делать это, как я сказал выше, следует только из самого фрагмента.

Если несколько раз сменить фрагмент то перелистывалка перестает работать. Есть подозрение что это из за того что они оба используют один supportFragmentManager.

По этому ничего сказать не могу. Исправь замечания выше, почитай на Android developers про фрагменты и их использование и проблема, скорее всего, исчезнет.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы