Fragmen atas masalah fragmen lain


271

Ketika saya menunjukkan satu fragmen (yang layar penuh dengan #77000000latar belakang) di atas fragmen lain (sebut saja utama), fragmen utama saya masih bereaksi terhadap klik (kita dapat mengklik tombol meskipun kita tidak melihatnya).

Pertanyaan : bagaimana mencegah klik pada fragmen pertama (utama)?

EDIT

Sayangnya, saya tidak bisa menyembunyikan fragmen utama, karena saya menggunakan latar belakang transparan pada fragmen kedua (jadi, pengguna dapat melihat apa yang ada di belakang).


Berdasarkan apa yang Anda memberi kami bekerja dengan, Anda harus mencoba pengaturan Visibilitydari Anda main Fragmentuntuk GONEketika Anda tidak menggunakannya.
adneal

1
Tanpa melihat bagaimana Anda menerapkan metode onClicked Anda, saya kira Anda mengembalikan "false" ketika diklik.
DeeV

@DeeV, onClickmetode tidak mengembalikan apa pun. Tapi Anda memberikan ide, terima kasih (saya akan segera mengirim jawaban).
Dmitry Zaytsev

1
Doh. Kamu benar. onTouch mengembalikannya. Saya hanya berharap saya mengerti mengapa acara sentuhan jatuh melalui sebuah fragmen. Seharusnya tidak melakukan itu jika Anda tidak mengeluarkan acara sentuh.
DeeV

@DeeV, sepertinya jika tampilan Anda (itu, misalnya di atas yang lain) tidak menangkap peristiwa onTouch, maka sistem terus mencari tampilan lain dengan koordinat yang sama.
Dmitry Zaytsev

Jawaban:


578

Setel clickableproperti pada tampilan fragmen kedua menjadi true. Tampilan akan menangkap acara sehingga tidak akan diteruskan ke fragmen utama. Jadi jika tampilan fragmen kedua adalah tata letak, ini akan menjadi kode:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:clickable="true" />

4
Ini berhasil untuk saya. Tampaknya lebih mudah daripada solusi yang diberikan @Dmitry Zaitsev di atas. Apakah ada alasan mengapa ini merupakan ide yang buruk? Saya sepertinya tidak bisa memikirkan apa pun, tetapi saya hanya ingin memastikan.
ariets

1
Ini tidak berhasil untuk saya. Saya memiliki bagian RelativeLayoutdalam fragmen, dan saya mengatur seluruh tampilan dengan clickeableproperti. Solusi dari @Dmitry menyelesaikan masalah saya.
4gus71n

3
Ini berhasil untuk saya. "Dapat diklik" di Android tampaknya agak seperti iOS '"userInteractionEnabled"
mvds

17
Mengapa Android membuat kami dalam kondisi pengkodean yang keras ?!
Lo-Tan

1
Saya mengalami masalah yang sama dengan ViewPager. Ketika saya gulir di halaman pertama, itu berpindah ke halaman kedua juga, dan solusi ini tidak berhasil untuk saya. Ada ide?
Gokhan Arik

72

Solusinya cukup sederhana. Dalam fragmen kedua kami (yang tumpang tindih dengan fragmen utama kami), kami hanya perlu menangkap onTouchperistiwa:

@Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstance){
    View root = somehowCreateView();

    /*here is an implementation*/

    root.setOnTouchListener(new View.OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
            return true;
        }
    });
    return root;
}

solusi Anda bekerja +1 untuk itu tetapi dapatkah Anda memberi tahu saya mengapa kami perlu melakukan ini secara eksplisit?
Berburu

@Hal Anda tidak perlu. Itu hanyalah cara lain untuk melakukannya (lihat jawaban yang diterima)
Dmitry Zaytsev

android: clickable = "true" pada tata letak utama xml fragmen Anda yang kedua.
Rishabh Srivastava

Ada masalah dengan solusi ini, ketika Anda masuk dalam mode aksesibilitas komentar balik AKTIF, itu tidak akan membaca elemen individu sebagai gantinya mendapatkan fokus ke tampilan root.
Amit Garg

Versi Kotlin: root.setOnTouchListener {_, _ -> true}
Gal Rom

21

Cukup tambahkan clickable="true"dan focusable="true"ke tata letak induk

 <android.support.constraint.ConstraintLayout
      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:clickable="true"
      android:focusable="true">

      <!--Your views-->

 </android.support.constraint.ConstraintLayout>

Jika Anda menggunakan AndroidX, coba ini

 <androidx.constraintlayout.widget.ConstraintLayout
      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:clickable="true"
      android:focusable="true">

          <!--Your views-->

 </androidx.constraintlayout.widget.ConstraintLayout>

Apakah ini berbeda dari jawaban yang diterima? focuseablesebenarnya tidak perlu.
Dmitry Zaytsev

2
Saya pikir di focusable="true"sini hanya untuk menghindari peringatan di Android Studio.
Artem M

9

Anda harus menyembunyikan fragmen pertama saat Anda menunjukkan Fragmen kedua jika dua fragmen ditempatkan dalam tampilan wadah yang sama.

Jika Anda ingin tahu lebih banyak pertanyaan tentang cara mengatasi masalah tentang Fragmen, Anda dapat melihat perpustakaan saya: https://github.com/JustKiddingBaby/FragmentRigger

FirstFragment firstfragment;
SecondFragment secondFragment;
FragmentManager fm;
FragmentTransaction ft=fm.beginTransaction();
ft.hide(firstfragment);
ft.show(secondFragment);
ft.commit();

1
Ini harus menjadi jawaban yang tepat! Terima kasih kawan Saya telah memecahkan pertanyaan ini di proyek lain. Tapi saya sudah lupa Bagaimana saya menyelesaikannya dan Akhirnya, saya mendapat jawaban Anda. Terima kasih.
Licat Julius

1
Saya rasa ini bukan solusi yang tepat. Fragmen / Kegiatan bekerja di tumpukan tampilan. Anda harus memanggil .show lagi setelah fragmen atas dikeluarkan dari tumpukan, yang berarti fragmen bawah harus diberi tahu bahwa fragmen atas hilang. Itu hanya ditambahkan logika ekstra untuk mempertahankan.
XY

4

Anda perlu menambahkan android:focusable="true"denganandroid:clickable="true"

Clickable berarti dapat diklik oleh perangkat penunjuk atau disadap oleh perangkat sentuh.

Focusableberarti dapat memperoleh fokus dari perangkat input seperti keyboard. Perangkat input seperti keyboard tidak dapat memutuskan tampilan mana yang akan dikirimi aktivitas input berdasarkan input itu sendiri, sehingga mereka mengirimnya ke tampilan yang memiliki fokus.


2
dan focusable = "true" diperlukan untuk menghindari peringatan di Android Studio baru
Hossam Hassan

2

Ada lebih dari satu solusi yang sebagian dari kita berkontribusi pada utas ini tetapi juga saya ingin menyebutkan satu solusi lain. Jika Anda tidak suka meletakkan yang dapat diklik dan fokus sama dengan benar untuk setiap tata letak ViewGroup dalam XML seperti saya. Anda juga dapat meletakkannya di pangkalan Anda jika Anda memiliki satu seperti di bawah ini;

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

        val rootView = inflater.inflate(layout, container, false).apply {
            isClickable = true
            isFocusable = true
        }

        return rootView
    }

Anda juga dapat menggunakan variabel sebaris tetapi saya tidak memilihnya karena alasan saya.

Saya harap ini membantu bagi mereka yang membenci tata letak XML.


1

Jawaban yang dapat diterima akan "bekerja", tetapi juga akan menyebabkan biaya kinerja (penarikan berlebih, pengukuran ulang pada perubahan orientasi) karena fragmen di bagian bawah masih ditarik. Mungkin Anda harus menemukan fragmen dengan tag atau ID dan mengatur visibilitas ke GONE atau VISIBLE ketika Anda perlu menampilkannya lagi.

Di Kotlin:

fragmentManager.findFragmentByTag(BottomFragment.TAG).view.visibility = GONE

Solusi ini lebih disukai daripada alternatif hide()dan show()metode FragmentTransactionketika Anda menggunakan animasi. Anda cukup menyebutnya dari onTransitionStart()dan onTransitionEnd()dari Transition.TransitionListener.


1

Metod 1:

Anda dapat menambahkan ke semua tata letak fragmen

android:clickable="true"
android:focusable="true"
android:background="@color/windowBackground"

Metod 2: (Secara terprogram)

Perpanjang semua fragmen dari FragmentBasedll. Kemudian tambahkan kode ini keFragmentBase

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    getView().setBackgroundColor(getResources().getColor(R.color.windowBackground));
    getView().setClickable(true);
    getView().setFocusable(true);
}

0

Apa yang dapat Anda lakukan adalah Anda dapat memberikan klik Kosong ke tata letak fragmen sebelumnya dengan menggunakan properti onClick ke tata letak induk dari fragmen utama dan dalam aktivitas Anda dapat membuat fungsi doNothing(View view)dan tidak menulis apa pun di dalamnya. Ini akan melakukannya untuk Anda.


0

Ini terdengar seperti kasing untuk DialogFragment. Kalau tidak, dengan Fragment Manager, komit satu untuk disembunyikan dan yang lain untuk ditampilkan. Itu berhasil bagi saya.


0

Penambahan android:clickable="true"tidak berfungsi untuk saya. Solusi ini tidak berfungsi di CoordinatorLayout saat itu adalah tata letak induk. Karena itulah saya menjadikan RelativeLayout sebagai tata letak induk, ditambahkan android:clickable="true"padanya dan menempatkan CoordinatorLayout pada RelativeLayout ini.


0

Saya memiliki beberapa fragmen dengan xml yang sama.
Setelah menghabiskan berjam-jam, saya melepas setPageTransformerdan mulai bekerja

   //  viewpager.setPageTransformer(false, new BackgPageTransformer())

Saya memiliki logika scalling.

public class BackgPageTransformer extends BaseTransformer {

    private static final float MIN_SCALE = 0.75f;

    @Override
    protected void onTransform(View view, float position) {
        //view.setScaleX Y
    }

    @Override
    protected boolean isPagingEnabled() {
        return true;
    }
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.