Mảnh vỡ trên một vấn đề mảnh vỡ khác


271

Khi tôi hiển thị một đoạn (toàn màn hình có #77000000nền) trên một đoạn khác (hãy gọi nó là chính), đoạn chính của tôi vẫn phản ứng với các nhấp chuột (chúng ta có thể nhấp vào nút ngay cả khi chúng ta không nhìn thấy nó).

Câu hỏi : làm thế nào để ngăn chặn nhấp chuột vào đoạn đầu tiên (chính)?

BIÊN TẬP

Thật không may, tôi không thể ẩn đoạn chính, vì tôi đang sử dụng nền trong suốt trên đoạn thứ hai (vì vậy, người dùng có thể thấy những gì nằm phía sau).


Dựa trên những gì bạn đã cho chúng tôi để làm việc với, bạn nên cố gắng thiết lập Visibilitycủa bạn main Fragmentđể GONEkhi bạn không sử dụng nó.
adneal

1
Không thấy cách bạn triển khai phương thức onClicky của mình, tôi đoán bạn sẽ trả về "false" khi nhấp vào.
DeeV

@DeeV, onClickphương thức không trả về bất cứ điều gì. Nhưng bạn đưa ra một ý tưởng, cảm ơn (tôi sẽ đăng câu trả lời sớm).
Dmitry Zaytsev

1
Cô ơi. Bạn đúng. onTouch trả lại nó. Tôi chỉ muốn tôi hiểu tại sao một sự kiện cảm ứng rơi qua một mảnh. Nó không nên làm điều đó nếu bạn không phát hành sự kiện chạm.
DeeV

@DeeV, trông giống như nếu chế độ xem của bạn (ví dụ như trên cùng) không bắt sự kiện onTouch, sau đó hệ thống tiếp tục tìm kiếm các chế độ xem khác có cùng tọa độ.
Dmitry Zaytsev

Câu trả lời:


577

Đặt thuộc clickabletính trên khung nhìn của đoạn thứ hai thành true. Chế độ xem sẽ bắt sự kiện để nó không được chuyển đến đoạn chính. Vì vậy, nếu khung nhìn của đoạn thứ hai là một bố cục, thì đây sẽ là mã:

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

4
Điều này làm việc cho tôi. Có vẻ như dễ dàng hơn giải pháp @Dmitry Zaitsev đã đưa ra ở trên. Có bất kỳ lý do tại sao điều này sẽ là một ý tưởng tồi? Tôi dường như không thể nghĩ về bất kỳ, nhưng tôi chỉ muốn chắc chắn.
ariets

1
Điều này đã không làm việc cho tôi. Tôi có một phần RelativeLayoutbên trong, và tôi đặt toàn bộ khung nhìn với clickeabletài sản. Giải pháp của @Dmitry giải quyết vấn đề của tôi.
4gus71n

3
Điều này làm việc cho tôi. "có thể nhấp" trong Android rõ ràng giống như "userInteractionEnables" của iOS
mvds

17
Tại sao Android khiến chúng ta phải chịu các điều kiện mã hóa khắc nghiệt?!
Lo-Tân

1
Tôi đang gặp vấn đề tương tự với ViewPager. Khi tôi cuộn trên trang đầu tiên, nó cũng chuyển sang trang thứ hai và giải pháp này không hiệu quả với tôi. Có ý kiến ​​gì không?
Gokhan Arik

72

Giải pháp khá đơn giản. Trong đoạn thứ hai của chúng tôi (phần này trùng với đoạn chính của chúng tôi), chúng ta chỉ cần bắt onTouchsự kiện:

@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;
}

giải pháp của bạn đã làm việc +1 cho điều đó nhưng bạn có thể cho tôi biết lý do tại sao chúng ta cần phải làm điều này một cách rõ ràng không?
Săn

@ Bạn không cần phải làm vậy. Đó chỉ là một cách khác để làm điều đó (xem câu trả lời được chấp nhận)
Dmitry Zaytsev

android: clickable = "true" trên bố cục chính xml của đoạn thứ hai của bạn.
Rishabh Srivastava

Có một vấn đề với giải pháp này, khi bạn ở chế độ đàm thoại khả năng truy cập BẬT, nó sẽ không đọc các phần tử riêng lẻ thay vào đó lấy tiêu điểm để xem gốc.
Amit Garg

Phiên bản Kotlin: root.setOnTouchListener {_, _ -> true}
Gal Rom

21

Chỉ cần thêm clickable="true"focusable="true"bố trí cha mẹ

 <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>

Nếu bạn đang sử dụng AndroidX, hãy thử điều này

 <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>

Đây có phải là một số khác nhau từ câu trả lời được chấp nhận? focuseablekhông thực sự cần thiết
Dmitry Zaytsev

2
Tôi nghĩ focusable="true"ở đây chỉ là để tránh một cảnh báo trong Android Studio.
Artem M

9

Bạn nên ẩn đoạn đầu tiên khi bạn đang hiển thị Đoạn thứ hai nếu hai mảnh được đặt trong cùng một khung nhìn.

Nếu bạn muốn biết thêm câu hỏi về cách giải quyết vấn đề về Fragment, bạn có thể xem thư viện của tôi: https://github.com/JustKiddingBaby/FragmentRigger

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

1
Đây phải là câu trả lời đúng! Cảm ơn bạn. Tôi đã giải quyết câu hỏi này trên một dự án khác. Nhưng tôi đã quên Làm thế nào tôi giải quyết nó và Cuối cùng, tôi đã nhận được câu trả lời của bạn. Cảm ơn bạn.
Licat Julius

1
Tôi không nghĩ rằng đây là giải pháp đúng đắn. Các mảnh / Hoạt động làm việc trong một ngăn xếp xem. Bạn sẽ phải gọi lại .show một lần nữa sau khi đoạn trên cùng được bật ra khỏi ngăn xếp, điều đó có nghĩa là đoạn dưới cùng phải được thông báo phần trên cùng đã biến mất. Nó chỉ cần thêm logic để duy trì.
XY

4

Bạn cần thêm android:focusable="true"vớiandroid:clickable="true"

Clickable có nghĩa là nó có thể được bấm bởi một thiết bị con trỏ hoặc được gõ bởi một thiết bị cảm ứng.

Focusablecó nghĩa là nó có thể lấy nét từ một thiết bị đầu vào như bàn phím. Các thiết bị đầu vào như bàn phím không thể quyết định chế độ xem nào sẽ gửi các sự kiện đầu vào của nó dựa trên chính các đầu vào, vì vậy chúng sẽ gửi chúng đến chế độ xem tập trung.


2
và Focusable = "true" là bắt buộc để tránh cảnh báo trong Android Studio mới
Hossam Hassan

2

Có nhiều hơn một giải pháp mà một số người trong chúng tôi đã đóng góp cho chủ đề này nhưng tôi cũng muốn đề cập đến một giải pháp khác. Nếu bạn không thích đặt có thể nhấp và có thể tập trung bằng với đúng Viewgroup gốc của mọi bố cục trong XML như tôi. Bạn cũng có thể đặt nó vào cơ sở của bạn nếu bạn có một cái giống như bên dưới;

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
    }

Bạn cũng có thể sử dụng biến nội tuyến nhưng tôi không thích nó vì lý do của tôi.

Tôi hy vọng nó sẽ giúp cho những người ghét XML bố cục.


1

Câu trả lời chấp nhận được sẽ "hoạt động", nhưng cũng sẽ gây ra chi phí hiệu suất (rút tiền, đo lại thay đổi định hướng) vì đoạn ở phía dưới vẫn đang được rút ra. Có lẽ bạn chỉ cần tìm đoạn bằng thẻ hoặc ID và đặt mức độ hiển thị thành Gone hoặc VISIBLE khi bạn cần hiển thị lại.

Trong Kotlin:

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

Giải pháp này thích hợp hơn với phương pháp thay thế hide()show()phương pháp FragmentTransactionkhi bạn sử dụng hình ảnh động. Bạn chỉ cần gọi nó từ onTransitionStart()onTransitionEnd()của Transition.TransitionListener.


1

Metod 1:

Bạn có thể thêm vào tất cả các bố cục mảnh

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

Metod 2: (Lập trình)

Mở rộng tất cả các đoạn từ FragmentBasevv Sau đó thêm mã này vàoFragmentBase

@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

Những gì bạn có thể làm là bạn có thể nhấp chuột vào bố cục của đoạn trước bằng cách sử dụng thuộc tính onClick để bố trí chính của đoạn đó và trong hoạt động bạn có thể tạo một hàm doNothing(View view)và không viết bất cứ điều gì trong đó. Điều này sẽ làm điều đó cho bạn.


0

Điều này nghe có vẻ như một trường hợp cho DialogFragment. Mặt khác, với Fragment Manager, hãy cam kết một cái để ẩn và cái còn lại hiển thị. Điều đó đã làm việc cho tôi.


0

Việc thêm android:clickable="true"không làm việc cho tôi. Giải pháp này không hoạt động trên Phối hợpLayout khi đó là bố trí chính. Đó là lý do tại sao tôi đã tạo RelativeLayout dưới dạng bố trí cha mẹ, thêm android:clickable="true"vào nó và đặt Điều phối viênLayout trên RelativeLayout này.


0

Tôi đã có nhiều mảnh với cùng xml.
Sau khi dành hàng giờ, tôi gỡ bỏ setPageTransformervà nó bắt đầu làm việc

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

Tôi đã logic logic.

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;
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.