Cách xử lý các nhấp chuột bằng cách sử dụng XML onClick trong Fragment


440

Pre-Honeycomb (Android 3), mỗi Hoạt động đã được đăng ký để xử lý các lần nhấp nút thông qua onClickthẻ trong XML của Bố cục:

android:onClick="myClickMethod"

Trong phương thức đó, bạn có thể sử dụng view.getId()và một câu lệnh chuyển đổi để thực hiện logic nút.

Với việc giới thiệu Honeycomb, tôi sẽ chia các Hoạt động này thành các Mảnh vỡ có thể được sử dụng lại trong nhiều Hoạt động khác nhau. Hầu hết hoạt động của các nút là hoạt động độc lập và tôi muốn mã nằm trong tệp Fragment mà không sử dụng phương thức cũ (trước 1.6) để đăng ký OnClickListenercho mỗi nút.

final Button button = (Button) findViewById(R.id.button_id);
button.setOnClickListener(new View.OnClickListener() {
    public void onClick(View v) {
        // Perform action on click
    }
});

Vấn đề là khi bố cục của tôi bị thổi phồng thì đó vẫn là Hoạt động lưu trữ đang nhận các lần nhấp nút chứ không phải các Đoạn riêng lẻ. Có một cách tiếp cận tốt cho một trong hai

  • Đăng ký đoạn để nhận nút bấm?
  • Truyền các sự kiện nhấp từ Hoạt động đến đoạn mà chúng thuộc về?

1
Bạn không thể xử lý việc nghe người đăng ký trong onCreate của đoạn?
CL22

24
@jodes Có, nhưng tôi không muốn phải sử dụng setOnClickListenerfindViewByIdvới mỗi nút, đó là lý do tại sao onClickđược thêm vào, để làm cho mọi thứ đơn giản hơn.
smith324

4
Nhìn vào câu trả lời được chấp nhận, tôi nghĩ rằng việc sử dụng setOnClickListener được kết nối lỏng lẻo hơn so với việc sử dụng phương pháp tiếp cận onClick XML. Nếu hoạt động phải 'chuyển tiếp' mỗi lần nhấp vào đúng đoạn, điều này có nghĩa là mã sẽ phải thay đổi mỗi khi một đoạn được thêm vào. Sử dụng một giao diện để tách rời khỏi lớp cơ sở của đoạn không giúp ích gì cho điều đó. Nếu đoạn đăng ký với chính nút đó, hoạt động vẫn hoàn toàn không biết đó là phong cách IMO tốt hơn. Xem thêm câu trả lời từ Adorjan Princz.
Adriaan Koster

@ smith324 phải đồng ý với Adriaan về điều này. Hãy xem câu trả lời của Adorjan và xem liệu cuộc sống có tốt hơn không sau đó.
dùng1567453

Câu trả lời:


175

Bạn chỉ có thể làm điều này:

Hoạt động:

Fragment someFragment;    

//...onCreate etc instantiating your fragments

public void myClickMethod(View v) {
    someFragment.myClickMethod(v);
}

Miếng:

public void myClickMethod(View v) {
    switch(v.getId()) {
        // Just like you were doing
    }
}    

Đáp lại @Ameen, người muốn ít ghép nối hơn nên các mảnh vỡ có thể được sử dụng lại

Giao diện:

public interface XmlClickable {
    void myClickMethod(View v);
}

Hoạt động:

XmlClickable someFragment;    

//...onCreate, etc. instantiating your fragments casting to your interface.
public void myClickMethod(View v) {
    someFragment.myClickMethod(v);
}

Miếng:

public class SomeFragment implements XmlClickable {

//...onCreateView, etc.

@Override
public void myClickMethod(View v) {
    switch(v.getId()){
        // Just like you were doing
    }
}    

52
Đó là những gì tôi đang làm về cơ bản nhưng sẽ rắc rối hơn rất nhiều khi bạn có nhiều đoạn mà mỗi phần cần nhận các sự kiện nhấp chuột. Tôi chỉ bị trầm trọng thêm với những mảnh vỡ nói chung vì các mô hình đã tan biến xung quanh chúng.
smith324

128
Tôi đang gặp vấn đề tương tự, và mặc dù tôi đánh giá cao phản hồi của bạn, đây không phải là mã sạch theo quan điểm kỹ thuật phần mềm. Mã này dẫn đến hoạt động được kết hợp chặt chẽ với đoạn. Bạn sẽ có thể sử dụng lại cùng một đoạn trong nhiều hoạt động mà không cần các hoạt động biết chi tiết triển khai của các đoạn.
Ameen

1
Nên là "switch (v.getId ()) {" chứ không phải "switch (v.getid ()) {"
eb80

5
Thay vì xác định Giao diện của riêng bạn, bạn có thể sử dụng OnClickListener đã có như Euporie đã đề cập.
fr00tyl00p

1
Tôi đã khóc khi đọc nó, đó là RẤT NHIỀU BOILERPLATE ... Câu trả lời dưới đây từ @AdorjanPrincz là cách để đi.
Wjdavis5

603

Tôi thích sử dụng giải pháp sau để xử lý các sự kiện onClick. Điều này cũng hoạt động cho Activity và Fragment.

public class StartFragment extends Fragment implements OnClickListener{

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        View v = inflater.inflate(R.layout.fragment_start, container, false);

        Button b = (Button) v.findViewById(R.id.StartButton);
        b.setOnClickListener(this);
        return v;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.StartButton:

            ...

            break;
        }
    }
}

9
Trong onCreateView, tôi lặp qua tất cả các mục con của Viewgroup v và đặt onclicklistener cho tất cả các phiên bản Nút mà tôi tìm thấy. Nó tốt hơn nhiều so với cài đặt thủ công trình nghe cho tất cả các nút.
Một người

17
Bình chọn. Điều này làm cho các mảnh có thể tái sử dụng. Nếu không thì tại sao lại dùng mảnh vỡ?
Boreas

44
Đây không phải là kỹ thuật tương tự được lập trình bởi Windows lập trình vào năm 1987 sao? Không phải lo lắng. Google di chuyển nhanh và tất cả là về năng suất của nhà phát triển. Tôi chắc chắn rằng sẽ không lâu nữa cho đến khi việc xử lý sự kiện diễn ra tốt như năm 1991-eara Visual Basic.
Edward Brey

7
nhập khẩu phù thủy bạn đã sử dụng cho OnClickListener? Intellij gợi ý cho tôi android.view.View.OnClickListener và nó không hoạt động: / (onClick không bao giờ chạy)
Lucas Jota

4
@NathanOsman Tôi nghĩ rằng Câu hỏi có liên quan đến xml onClick, vì vậy các ans được chấp nhận cung cấp giải pháp chính xác.
Naveed Ahmad

29

Vấn đề tôi nghĩ là quan điểm vẫn là hoạt động chứ không phải là đoạn. Các mảnh vỡ không có bất kỳ khung nhìn độc lập nào của riêng nó và được đính kèm với khung nhìn hoạt động chính. Đó là lý do tại sao sự kiện kết thúc trong Hoạt động, không phải là đoạn. Thật không may, nhưng tôi nghĩ bạn sẽ cần một số mã để thực hiện công việc này.

Những gì tôi đã làm trong quá trình chuyển đổi chỉ đơn giản là thêm một trình nghe nhấp chuột gọi trình xử lý sự kiện cũ.

ví dụ:

final Button loginButton = (Button) view.findViewById(R.id.loginButton);
loginButton.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(final View v) {
        onLoginClicked(v);
    }
});

1
Cảm ơn - Tôi đã sử dụng điều này với một sửa đổi nhỏ trong đó tôi chuyển qua chế độ xem phân đoạn (ví dụ: kết quả của Inflater.inflate (R.layout.my_fragment_xml_resource)) để onLoginClicky () để nó có thể truy cập vào các chế độ xem phân đoạn, chẳng hạn như EditText, thông qua view.findViewById () (Nếu tôi chỉ đơn giản chuyển qua chế độ xem hoạt động, hãy gọi tới view.findViewById (R.id.myfragmentwidget_id) trả về null).
Michael Nelson

Điều này không hoạt động với API 21 trong dự án của tôi. Bất kỳ suy nghĩ về cách sử dụng phương pháp này?
Darth

Mã khá cơ bản của nó, được sử dụng trong khá nhiều ứng dụng. Bạn có thể mô tả những gì đang xảy ra cho bạn?
Brill Pappin

1
Đặt câu trả lời của tôi cho câu trả lời này để giải thích vấn đề xảy ra do bố cục của đoạn được gắn với chế độ xem của hoạt động.
fllo

25

Gần đây tôi đã giải quyết vấn đề này mà không phải thêm phương thức vào Hoạt động ngữ cảnh hoặc phải triển khai OnClickListener. Tôi không chắc đó có phải là một giải pháp "hợp lệ" hay không, nhưng nó hoạt động.

Dựa trên: https://developer.android.com/tools/data-binding/guide.html#binding_events

Nó có thể được thực hiện với các ràng buộc dữ liệu: Chỉ cần thêm thể hiện đoạn của bạn dưới dạng một biến, sau đó bạn có thể liên kết bất kỳ phương thức nào với onClick.

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.example.testapp.fragments.CustomFragment">

    <data>
        <variable android:name="fragment" android:type="com.example.testapp.fragments.CustomFragment"/>
    </data>
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ImageButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_place_black_24dp"
            android:onClick="@{() -> fragment.buttonClicked()}"/>
    </LinearLayout>
</layout>

Và đoạn mã liên kết sẽ là ...

public class CustomFragment extends Fragment {

    ...

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_person_profile, container, false);
        FragmentCustomBinding binding = DataBindingUtil.bind(view);
        binding.setFragment(this);
        return view;
    }

    ...

}

1
Tôi chỉ có một cảm giác, một số chi tiết bị thiếu vì tôi không thể làm cho giải pháp này hoạt động
Tima

Có thể bạn đang thiếu thứ gì đó từ "Môi trường xây dựng" trong tài liệu: developer.android.com/tools/data-binding/
mẹo

@Aldo Đối với phương thức onClick trong XML, tôi tin rằng bạn nên có android: onClick = "@ {() -> đoạn. ButtonClicky ()}" thay vào đó. Ngoài ra, đối với những người khác, bạn nên khai báo hàm buttonClicky () bên trong đoạn và đặt logic của bạn vào bên trong.
Hayk Nahapetyan

trong xml nên làandroid:name="fragment" android:type="com.example.testapp.fragments.CustomFragment"/>
COYG

1
Tôi chỉ cố gắng này và nametypecác thuộc tính của variablethẻ nên khôngandroid:tiền tố. Có lẽ có một phiên bản cũ của bố trí Android không yêu cầu nó?
JohnnyLambada

6

ButterKnife có lẽ là giải pháp tốt nhất cho vấn đề lộn xộn. Nó sử dụng các bộ xử lý chú thích để tạo mã cái gọi là "phương thức cũ".

Nhưng phương pháp onClick vẫn có thể được sử dụng, với một bộ lọc tùy chỉnh.

Cách sử dụng

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup cnt, Bundle state) {
    inflater = FragmentInflatorFactory.inflatorFor(inflater, this);
    return inflater.inflate(R.layout.fragment_main, cnt, false);
}

Thực hiện

public class FragmentInflatorFactory implements LayoutInflater.Factory {

    private static final int[] sWantedAttrs = { android.R.attr.onClick };

    private static final Method sOnCreateViewMethod;
    static {
        // We could duplicate its functionallity.. or just ignore its a protected method.
        try {
            Method method = LayoutInflater.class.getDeclaredMethod(
                    "onCreateView", String.class, AttributeSet.class);
            method.setAccessible(true);
            sOnCreateViewMethod = method;
        } catch (NoSuchMethodException e) {
            // Public API: Should not happen.
            throw new RuntimeException(e);
        }
    }

    private final LayoutInflater mInflator;
    private final Object mFragment;

    public FragmentInflatorFactory(LayoutInflater delegate, Object fragment) {
        if (delegate == null || fragment == null) {
            throw new NullPointerException();
        }
        mInflator = delegate;
        mFragment = fragment;
    }

    public static LayoutInflater inflatorFor(LayoutInflater original, Object fragment) {
        LayoutInflater inflator = original.cloneInContext(original.getContext());
        FragmentInflatorFactory factory = new FragmentInflatorFactory(inflator, fragment);
        inflator.setFactory(factory);
        return inflator;
    }

    @Override
    public View onCreateView(String name, Context context, AttributeSet attrs) {
        if ("fragment".equals(name)) {
            // Let the Activity ("private factory") handle it
            return null;
        }

        View view = null;

        if (name.indexOf('.') == -1) {
            try {
                view = (View) sOnCreateViewMethod.invoke(mInflator, name, attrs);
            } catch (IllegalAccessException e) {
                throw new AssertionError(e);
            } catch (InvocationTargetException e) {
                if (e.getCause() instanceof ClassNotFoundException) {
                    return null;
                }
                throw new RuntimeException(e);
            }
        } else {
            try {
                view = mInflator.createView(name, null, attrs);
            } catch (ClassNotFoundException e) {
                return null;
            }
        }

        TypedArray a = context.obtainStyledAttributes(attrs, sWantedAttrs);
        String methodName = a.getString(0);
        a.recycle();

        if (methodName != null) {
            view.setOnClickListener(new FragmentClickListener(mFragment, methodName));
        }
        return view;
    }

    private static class FragmentClickListener implements OnClickListener {

        private final Object mFragment;
        private final String mMethodName;
        private Method mMethod;

        public FragmentClickListener(Object fragment, String methodName) {
            mFragment = fragment;
            mMethodName = methodName;
        }

        @Override
        public void onClick(View v) {
            if (mMethod == null) {
                Class<?> clazz = mFragment.getClass();
                try {
                    mMethod = clazz.getMethod(mMethodName, View.class);
                } catch (NoSuchMethodException e) {
                    throw new IllegalStateException(
                            "Cannot find public method " + mMethodName + "(View) on "
                                    + clazz + " for onClick");
                }
            }

            try {
                mMethod.invoke(mFragment, v);
            } catch (InvocationTargetException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new AssertionError(e);
            }
        }
    }
}

6

Tôi thà đi xử lý nhấp chuột trong mã hơn là sử dụng onClickthuộc tính trong XML khi làm việc với các đoạn.

Điều này càng trở nên dễ dàng hơn khi di chuyển các hoạt động của bạn thành các mảnh. Bạn chỉ có thể gọi trình xử lý nhấp chuột (trước đây được đặt thành android:onClickXML) từ mỗi casekhối.

findViewById(R.id.button_login).setOnClickListener(clickListener);
...

OnClickListener clickListener = new OnClickListener() {
    @Override
    public void onClick(final View v) {
        switch(v.getId()) {
           case R.id.button_login:
              // Which is supposed to be called automatically in your
              // activity, which has now changed to a fragment.
              onLoginClick(v);
              break;

           case R.id.button_logout:
              ...
        }
    }
}

Khi nói đến việc xử lý các nhấp chuột theo từng mảnh, điều này có vẻ đơn giản hơn đối với tôi android:onClick.


5

Đây là một cách khác

1. Tạo một BaseFragment như thế này:

public abstract class BaseFragment extends Fragment implements OnClickListener

2.Sử dụng

public class FragmentA extends BaseFragment 

thay vì

public class FragmentA extends Fragment

3. Trong hoạt động của bạn:

public class MainActivity extends ActionBarActivity implements OnClickListener

BaseFragment fragment = new FragmentA;

public void onClick(View v){
    fragment.onClick(v);
}

Hy vọng nó giúp.


1 năm, 1 tháng và 1 ngày sau câu trả lời của bạn: Có lý do nào khác ngoài việc không lặp lại việc triển khai OnClickListener trên mỗi lớp Fragment để tạo BaseFragment trừu tượng không?
Dimitrios K.

5

Trong trường hợp sử dụng của tôi, tôi có 50 ImageView lẻ tôi cần để nối vào một phương thức onClick duy nhất. Giải pháp của tôi là lặp qua các khung nhìn bên trong đoạn và đặt cùng một trình nghe onclick trên mỗi khung:

    final View.OnClickListener imageOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            chosenImage = ((ImageButton)v).getDrawable();
        }
    };

    ViewGroup root = (ViewGroup) getView().findViewById(R.id.imagesParentView);
    int childViewCount = root.getChildCount();
    for (int i=0; i < childViewCount; i++){
        View image = root.getChildAt(i);
        if (image instanceof ImageButton) {
            ((ImageButton)image).setOnClickListener(imageOnClickListener);
        }
    }

2

Như tôi thấy câu trả lời họ bằng cách nào đó cũ. Gần đây, Google giới thiệu DataBinding , dễ dàng hơn để xử lý onClick hoặc gán trong xml của bạn.

Đây là một ví dụ tốt mà bạn có thể thấy cách xử lý này:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
       <variable name="handlers" type="com.example.Handlers"/>
       <variable name="user" type="com.example.User"/>
   </data>
   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
       <TextView android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{user.firstName}"
           android:onClick="@{user.isFriend ? handlers.onClickFriend : handlers.onClickEnemy}"/>
       <TextView android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{user.lastName}"
           android:onClick="@{user.isFriend ? handlers.onClickFriend : handlers.onClickEnemy}"/>
   </LinearLayout>
</layout>

Ngoài ra còn có hướng dẫn rất hay về DataBinding bạn có thể tìm thấy ở đây .


2

Bạn có thể định nghĩa một cuộc gọi lại như là một thuộc tính của bố cục XML của bạn. Bài viết Thuộc tính XML tùy chỉnh cho các tiện ích Android tùy chỉnh của bạn sẽ chỉ cho bạn cách làm điều đó cho một tiện ích tùy chỉnh. Tín dụng cho Kevin Dion :)

Tôi đang điều tra xem liệu tôi có thể thêm các thuộc tính có thể tạo kiểu cho lớp Fragment cơ sở hay không.

Ý tưởng cơ bản là có cùng chức năng mà View thực hiện khi xử lý cuộc gọi lại onClick.


1

Thêm vào câu trả lời của Blundell,
Nếu bạn có nhiều mảnh vỡ hơn, với nhiều onClicks:

Hoạt động:

Fragment someFragment1 = (Fragment)getFragmentManager().findFragmentByTag("someFragment1 "); 
Fragment someFragment2 = (Fragment)getFragmentManager().findFragmentByTag("someFragment2 "); 
Fragment someFragment3 = (Fragment)getFragmentManager().findFragmentByTag("someFragment3 "); 

...onCreate etc instantiating your fragments

public void myClickMethod(View v){
  if (someFragment1.isVisible()) {
       someFragment1.myClickMethod(v);
  }else if(someFragment2.isVisible()){
       someFragment2.myClickMethod(v);
  }else if(someFragment3.isVisible()){
       someFragment3.myClickMethod(v); 
  }

} 

Trong mảnh vỡ của bạn:

  public void myClickMethod(View v){
     switch(v.getid()){
       // Just like you were doing
     }
  } 

1

Nếu bạn đăng ký trong xml bằng android: Onclick = "", cuộc gọi lại sẽ được trao cho Hoạt động được tôn trọng trong bối cảnh mà đoạn của bạn thuộc về (getActivity ()). Nếu phương thức đó không được tìm thấy trong Hoạt động, thì hệ thống sẽ đưa ra một ngoại lệ.


cảm ơn, không ai khác giải thích lý do tại sao sự cố xảy ra

1

Bạn có thể muốn xem xét sử dụng EventBus cho các sự kiện được tách riêng .. Bạn có thể nghe các sự kiện rất dễ dàng. Bạn cũng có thể đảm bảo sự kiện đang được nhận trên chuỗi ui (thay vì gọi runOnUiThread .. cho chính mình cho mỗi lần đăng ký sự kiện)

https://github.com/greenrobot/EventBus

từ Github:

Xe buýt sự kiện được tối ưu hóa cho Android giúp đơn giản hóa việc liên lạc giữa các Hoạt động, Đoạn, Chủ đề, Dịch vụ, v.v. Ít mã hơn, chất lượng tốt hơn


1

Tôi muốn thêm vào câu trả lời của Adjorn Linkz .

Nếu bạn cần nhiều trình xử lý, bạn chỉ có thể sử dụng tài liệu tham khảo lambda

void onViewCreated(View view, Bundle savedInstanceState)
{
    view.setOnClickListener(this::handler);
}
void handler(View v)
{
    ...
}

Mẹo ở đây là handlerchữ ký của phương thức khớp với View.OnClickListener.onClickchữ ký. Bằng cách này, bạn sẽ không cần View.OnClickListenergiao diện.

Ngoài ra, bạn sẽ không cần bất kỳ báo cáo chuyển đổi.

Đáng buồn thay, phương pháp này chỉ giới hạn ở các giao diện yêu cầu một phương thức duy nhất hoặc lambda.


1

Mặc dù tôi đã phát hiện ra một số câu trả lời hay dựa vào ràng buộc dữ liệu, tôi không thấy bất kỳ điều gì sẽ đi đến toàn bộ với cách tiếp cận đó - theo nghĩa là cho phép phân giải đoạn trong khi cho phép định nghĩa bố cục không có đoạn trong XML.

Vì vậy, giả sử ràng buộc dữ liệu được kích hoạt, đây là một giải pháp chung tôi có thể đề xuất; Một chút dài nhưng nó chắc chắn hoạt động (với một số hãy cẩn thận):

Bước 1: Thực hiện OnClick tùy chỉnh

Điều này sẽ chạy một tìm kiếm nhận biết phân đoạn thông qua các bối cảnh được liên kết với chế độ xem khai thác (ví dụ: nút):


// CustomOnClick.kt

@file:JvmName("CustomOnClick")

package com.example

import android.app.Activity
import android.content.Context
import android.content.ContextWrapper
import android.view.View
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import java.lang.reflect.Method

fun onClick(view: View, methodName: String) {
    resolveOnClickInvocation(view, methodName)?.invoke(view)
}

private data class OnClickInvocation(val obj: Any, val method: Method) {
    fun invoke(view: View) {
        method.invoke(obj, view)
    }
}

private fun resolveOnClickInvocation(view: View, methodName: String): OnClickInvocation? =
    searchContexts(view) { context ->
        var invocation: OnClickInvocation? = null
        if (context is Activity) {
            val activity = context as? FragmentActivity
                    ?: throw IllegalStateException("A non-FragmentActivity is not supported (looking up an onClick handler of $view)")

            invocation = getTopFragment(activity)?.let { fragment ->
                resolveInvocation(fragment, methodName)
            }?: resolveInvocation(context, methodName)
        }
        invocation
    }

private fun getTopFragment(activity: FragmentActivity): Fragment? {
    val fragments = activity.supportFragmentManager.fragments
    return if (fragments.isEmpty()) null else fragments.last()
}

private fun resolveInvocation(target: Any, methodName: String): OnClickInvocation? =
    try {
        val method = target.javaClass.getMethod(methodName, View::class.java)
        OnClickInvocation(target, method)
    } catch (e: NoSuchMethodException) {
        null
    }

private fun <T: Any> searchContexts(view: View, matcher: (context: Context) -> T?): T? {
    var context = view.context
    while (context != null && context is ContextWrapper) {
        val result = matcher(context)
        if (result == null) {
            context = context.baseContext
        } else {
            return result
        }
    }
    return null
}

Lưu ý: dựa trên cách triển khai Android ban đầu (xem https://android.googlesource.com/pl platform / frameworks / base / + / a175a5b / core / java / android / view / View.java # 3025 )

Bước 2: Ứng dụng khai báo trong tệp bố cục

Sau đó, trong XML nhận biết ràng buộc dữ liệu:

<layout>
  <data>
     <import type="com.example.CustomOnClick"/>
  </data>

  <Button
    android:onClick='@{(v) -> CustomOnClick.onClick(v, "myClickMethod")}'
  </Button>
</layout>

Hãy cẩn thận

  • Giả sử FragmentActivitythực hiện dựa trên 'hiện đại'
  • Chỉ có thể tra cứu phương pháp của đoạn "trên cùng" (tức là cuối cùng ) trong ngăn xếp (mặc dù điều đó có thể được sửa, nếu cần)

0

Điều này đã làm việc cho tôi: (Android studio)

 @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.update_credential, container, false);
        Button bt_login = (Button) rootView.findViewById(R.id.btnSend);

        bt_login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                System.out.println("Hi its me");


            }// end onClick
        });

        return rootView;

    }// end onCreateView

1
Điều này trùng lặp câu trả lời của @Brill Pappin .
naXa

0

Giải pháp tốt nhất IMHO:

trong đoạn:

protected void addClick(int id) {
    try {
        getView().findViewById(id).setOnClickListener(this);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public void onClick(View v) {
    if (v.getId()==R.id.myButton) {
        onMyButtonClick(v);
    }
}

sau đó trong Fragment's onViewStateRestored:

addClick(R.id.myButton);

0

Hoạt động của bạn đang nhận được cuộc gọi lại như đã sử dụng:

mViewPagerCloth.setOnClickListener((YourActivityName)getActivity());

Nếu bạn muốn đoạn của mình nhận được cuộc gọi lại thì hãy làm điều này:

mViewPagerCloth.setOnClickListener(this);

và thực hiện onClickListenergiao diện trên Fragment

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.