एक्सएमएल के भीतर एक्सग्लिक्स पर क्लिक करके बटन क्लिक को कैसे हैंडल करें


440

प्री-हनीकॉम्ब (Android 3), onClickलेआउट के XML में टैग के माध्यम से बटन क्लिक को संभालने के लिए प्रत्येक गतिविधि को पंजीकृत किया गया था :

android:onClick="myClickMethod"

उस पद्धति के भीतर आप view.getId()बटन लॉजिक करने के लिए एक स्विच स्टेटमेंट का उपयोग कर सकते हैं ।

हनीकॉम्ब की शुरुआत के साथ, मैं इन गतिविधियों को खंडों में तोड़ रहा हूं जिन्हें कई अलग-अलग गतिविधियों के अंदर पुन: उपयोग किया जा सकता है। बटनों का अधिकांश व्यवहार गतिविधि स्वतंत्र है, और मैं प्रत्येक बटन के लिए पंजीकरण करने की पुरानी (पूर्व 1.6) पद्धति का उपयोग किए बिना कोड को फ्रैगमेंट फ़ाइल के अंदर निवास करना चाहूंगा OnClickListener

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

समस्या यह है कि जब मेरे लेआउट को फुलाया जाता है तो यह अभी भी होस्टिंग गतिविधि है जो बटन क्लिक प्राप्त कर रहा है, न कि व्यक्तिगत फ्रेगमेंट। क्या कोई अच्छा तरीका है

  • बटन क्लिक प्राप्त करने के लिए टुकड़े को पंजीकृत करें?
  • गतिविधि से उस खंड तक क्लिक इवेंट पास करें जो वे संबंधित हैं?

1
क्या आप टुकड़ा के onCreate के भीतर श्रोताओं को पंजीकृत करने का काम नहीं कर सकते?
सीएल

24
@ जजेस हां, लेकिन मैं उपयोग नहीं करना चाहता हूं setOnClickListenerऔर findViewByIdप्रत्येक बटन के लिए, यही कारण है कि onClickचीजों को सरल बनाने के लिए जोड़ा गया था।
smith324

4
मेरे द्वारा स्वीकार किए गए उत्तर को देखते हुए मुझे लगता है कि setOnClickListener का उपयोग XML पर क्लिक करने की तुलना में अधिक शिथिल है। यदि गतिविधि को सही टुकड़े पर प्रत्येक क्लिक को 'फॉरवर्ड' करना है, तो इसका मतलब है कि कोड को हर बार एक टुकड़ा जोड़ने पर बदलना होगा। खंड के आधार वर्ग से अलग करने के लिए एक इंटरफ़ेस का उपयोग करना उस के साथ मदद नहीं करता है। यदि टुकड़ा स्वयं सही बटन के साथ पंजीकृत होता है, तो गतिविधि पूरी तरह से अज्ञेय बनी रहती है जो बेहतर स्टाइल IMO है। Adorjan Princz का उत्तर भी देखें।
एड्रियन कोस्टर

@ smith324 को इस पर एड्रियन से सहमत होना होगा। Adorjan के उत्तर पर जाएं और देखें कि क्या उसके बाद जीवन बेहतर नहीं है।
user1567453

जवाबों:


175

आप ऐसा कर सकते हैं:

गतिविधि:

Fragment someFragment;    

//...onCreate etc instantiating your fragments

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

टुकड़ा:

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

@Ameen के जवाब में, जो कम कपलिंग चाहते थे ताकि फ्रैगमेंट पुन: प्रयोज्य हो

इंटरफेस:

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

गतिविधि:

XmlClickable someFragment;    

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

टुकड़ा:

public class SomeFragment implements XmlClickable {

//...onCreateView, etc.

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

52
यही मैं अब अनिवार्य रूप से कर रहा हूं, लेकिन यह बहुत अधिक गड़बड़ है जब आपके पास कई टुकड़े हैं जो प्रत्येक को क्लिक इवेंट प्राप्त करने की आवश्यकता है। मैं सामान्य रूप से केवल टुकड़ों के साथ उत्तेजित हूं क्योंकि प्रतिमान उनके चारों ओर घुल चुके हैं।
smith324

128
मैं एक ही मुद्दे में चल रहा हूं, और भले ही मैं आपकी प्रतिक्रिया की सराहना करता हूं, यह सॉफ्टवेयर इंजीनियरिंग दृष्टिकोण से साफ कोड नहीं है। इस कोड के परिणामस्वरूप गतिविधि को टुकड़े के साथ कसकर जोड़ा जा रहा है। टुकड़ों के कार्यान्वयन के विवरण को जानने के बिना आपको कई गतिविधियों में एक ही टुकड़े का फिर से उपयोग करने में सक्षम होना चाहिए।
अमीन

1
"स्विच (v.getId ()) {" होना चाहिए न कि "स्विच (v.getid ()) {"
eb80

5
अपने स्वयं के इंटरफ़ेस को परिभाषित करने के बजाय, आप पहले से मौजूद OnClickListener का उपयोग कर सकते हैं जैसा कि Euporie द्वारा उल्लेख किया गया है।
fr00tyl00p सेप

1
जब मैंने इसे पढ़ा तो मैं रोया, यह SO MUCH BOILERPLATE है ... @ AdorjanPrincz से नीचे का उत्तर जाने का रास्ता है।
Wjdavis5

603

मैं ऑनक्लिक घटनाओं को संभालने के लिए निम्नलिखित समाधान का उपयोग करना पसंद करता हूं। यह एक्टिविटी और फ्रैगमेंट के लिए भी काम करता है।

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
OnCreateView में, मैं ViewGroup v के सभी चाइल्ड आइटमों के माध्यम से लूप करता हूं और सभी बटन इंस्टेंस के लिए ऑनक्लीक्लेंसर सेट करता हूं जो मुझे मिलता है। यह सभी बटन के लिए श्रोता को मैन्युअल रूप से सेट करने से बहुत बेहतर है।
एक व्यक्ति

17
मतदान किया। यह टुकड़ों को पुन: प्रयोज्य बनाता है। अन्यथा टुकड़ों का उपयोग क्यों?
बोरियास

44
क्या यह वही तकनीक नहीं है जिसकी 1987 में विंडोज को प्रोग्रामिंग करके वकालत की गई थी। कोइ चिंता नहीं। Google तेजी से आगे बढ़ता है और सभी डेवलपर उत्पादकता के बारे में है। मुझे यकीन है कि यह तब तक लंबा नहीं होगा जब तक कि ईवेंट हैंडलिंग 1991-एरा विज़ुअल बेसिक जितना अच्छा नहीं हो जाता।
एडवर्ड ब्रे

7
चुड़ैल आयात आप OnClickListener के लिए इस्तेमाल किया है? Intellij मुझे android.view.View.nClickListener का सुझाव देता है और यह काम नहीं करता है: / (onClick कभी नहीं चलता)
लुकास जोटा

4
@NathanOsman मुझे लगता है कि प्रश्न xml onClick से संबंधित था, इसलिए स्वीकृत ans सटीक समाधान प्रदान करते हैं।
नावेद अहमद

29

मुझे लगता है कि समस्या अभी भी गतिविधि है, न कि टुकड़ा। अंशों का अपना कोई स्वतंत्र दृष्टिकोण नहीं होता है और यह माता-पिता की गतिविधियों के दृश्य से जुड़ा होता है। यही कारण है कि घटना गतिविधि में समाप्त होती है, खंड नहीं। यह दुर्भाग्यपूर्ण है, लेकिन मुझे लगता है कि इस काम को करने के लिए आपको कुछ कोड की आवश्यकता होगी।

रूपांतरणों के दौरान मैं जो कर रहा हूं वह बस एक क्लिक श्रोता को जोड़ना है जो पुराने ईवेंट हैंडलर को बुलाता है।

उदाहरण के लिए:

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

1
धन्यवाद - मैंने इसे एक मामूली संशोधन के साथ प्रयोग किया है जिसमें मैं अंश दृश्य देख रहा हूं (अर्थात inflater.inflate (R.layout.my_fragment_xml_resource) का परिणाम onLoginClicked पर (ताकि यह टुकड़े उप-दृश्य तक पहुंच सके) एक EditText के रूप में, view.findViewById के माध्यम से () (यदि मैं बस गतिविधि दृश्य से गुजरता हूं, तो view.findViewById (R.id.myfragmentwidget_id) रिटर्न शून्य) को कॉल करता है।
माइकल नेल्सन

यह मेरी परियोजना में एपीआई 21 के साथ काम नहीं करता है। इस दृष्टिकोण का उपयोग करने के बारे में कोई विचार?
डार्थ कोडर

इसका सुंदर मूल कोड, प्रत्येक ऐप में बहुत अधिक उपयोग किया जाता है। क्या आप बता सकते हैं कि आपके लिए क्या हो रहा है?
ब्रिल पप्पिन

1
समस्या के स्पष्टीकरण के लिए इस उत्तर के लिए मेरा उत्थान करें, क्योंकि टुकड़ा का लेआउट गतिविधि के दृष्टिकोण से जुड़ा हुआ है।
फ्लो

25

मैंने हाल ही में इस गतिविधि को संदर्भ गतिविधि में एक विधि जोड़े बिना या OnClickListener को लागू करने के लिए हल किया है। मुझे यकीन नहीं है कि यह "वैध" समाधान है न तो, लेकिन यह काम करता है।

इसके आधार पर: https://developer.android.com/tools/data-binding/guide.html#binding_events

यह डेटा बाइंडिंग के साथ किया जा सकता है: बस एक चर के रूप में अपने टुकड़े का उदाहरण जोड़ें, फिर आप किसी भी विधि को ऑनक्लिक के साथ लिंक कर सकते हैं।

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

और टुकड़ा लिंक कोड होगा ...

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
मुझे बस एक एहसास है, कुछ विवरण गायब हैं क्योंकि मैं इस समाधान का काम नहीं कर पा रहा हूं
Tima

हो सकता है कि आपके दस्तावेज में "बिल्ड एनवायरनमेंट" से कुछ याद आ रहा हो: developer.android.com/tools/data-binding/…
Aldo Canepa

@Aldo XML में onClick विधि के लिए मेरा मानना ​​है कि आपके पास android होना चाहिए: onClick = "@ {()> टुकड़ा। बटन क्लिक करें ()}" के बजाय। दूसरों के लिए भी, आपको खंड के अंदर बटन क्लिच () फ़ंक्शन की घोषणा करनी चाहिए और अपने तर्क को अंदर रखना चाहिए।
बजे हेक नाहापत्तन

xml में यह होना चाहिएandroid:name="fragment" android:type="com.example.testapp.fragments.CustomFragment"/>
COYG

1
मैं सिर्फ यह और कोशिश की nameऔर typeकी विशेषताओं का variableटैग चाहिए नहीं है android:उपसर्ग। शायद एंड्रॉइड लेआउट का एक पुराना संस्करण है जिसे इसकी आवश्यकता है?
JohnnyLambada

6

बटरकनीफ अव्यवस्था समस्या के लिए शायद सबसे अच्छा समाधान है। यह तथाकथित "पुरानी विधि" बॉयलरप्लेट कोड उत्पन्न करने के लिए एनोटेशन प्रोसेसर का उपयोग करता है।

लेकिन ऑनकिक विधि का उपयोग अभी भी किया जा सकता है, एक कस्टम इनफ्लोटर के साथ।

कैसे इस्तेमाल करे

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

कार्यान्वयन

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

मैं बजाय कोड में क्लिक हैंडलिंग के लिए जाना होगा onClickXML में विशेषता का उपयोग करते समय टुकड़े के साथ।

यह तब और भी आसान हो जाता है, जब आपकी गतिविधियाँ टुकड़ों में हो जाती हैं। आप बस android:onClickप्रत्येक caseब्लॉक से सीधे क्लिक हैंडलर ( एक्सएमएल में पहले से सेट ) को कॉल कर सकते हैं ।

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:
              ...
        }
    }
}

जब टुकड़ों में क्लिक को संभालने की बात आती है, तो यह मेरे लिए सरल लगता है android:onClick


5

यह एक और तरीका है :

1. इस तरह एक BaseFragment बनाएँ:

public abstract class BaseFragment extends Fragment implements OnClickListener

2.Use

public class FragmentA extends BaseFragment 

के बजाय

public class FragmentA extends Fragment

3. अपनी गतिविधि में:

public class MainActivity extends ActionBarActivity implements OnClickListener

तथा

BaseFragment fragment = new FragmentA;

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

आशा है ये मदद करेगा।


आपके उत्तर के बाद 1 वर्ष, 1 महीना और 1 दिन: क्या कोई ऐसा कारण है जो अमूर्त BaseFragment बनाने के लिए प्रत्येक Fragment वर्ग पर OnClickListener को लागू नहीं करने के अलावा है?
दिमित्रियोस के

5

मेरे उपयोग के मामले में, मेरे पास 50 विषम चित्र हैं जिन्हें मुझे एक सिंगल ऑनक्लिक विधि में हुक करने की आवश्यकता है। मेरा समाधान टुकड़े के अंदर के विचारों पर लूप करना है और प्रत्येक पर एक ही ऑन्क्लिक श्रोता सेट करना है:

    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

जैसा कि मैंने उत्तर देखा कि वे किसी तरह पुराने हैं। हाल ही में Google ने DataBinding की शुरुआत की है जो onClick को संभालने में बहुत आसान है आपके xml में या असाइन करने में ।

यहाँ अच्छा उदाहरण है जिसे आप देख सकते हैं कि इसे कैसे संभालना है:

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

डेटाबाइंडिंग के बारे में भी बहुत अच्छा ट्यूटोरियल है आप इसे यहाँ पा सकते हैं ।


2

आप अपने XML लेआउट की विशेषता के रूप में कॉलबैक को परिभाषित कर सकते हैं। लेख कस्टम XML आपके कस्टम Android विजेट के लिए विशेषताएँ आपको दिखाएगा कि कस्टम विजेट के लिए यह कैसे करना है। श्रेय केविन डायोन को जाता है :)

मैं जांच कर रहा हूं कि क्या मैं आधार फ्रेगमेंट वर्ग में शैलीगत विशेषताओं को जोड़ सकता हूं।

मूल विचार में वही कार्यक्षमता है जो ऑनक्लिक कॉलबैक से निपटने के दौरान कार्यान्वयन को देखें।


1

ब्लंडेल के उत्तर में जोड़ना,
यदि आपके पास अधिक टुकड़े हैं, तो बहुत सारे ऑनक्लेक्स:

गतिविधि:

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

} 

आपके टुकड़े में:

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

1

यदि आप android: Onclick = "" का उपयोग करके xml में पंजीकरण करते हैं, तो कॉलबैक संबंधित गतिविधि को दिया जाएगा, जिसके संदर्भ में आपका टुकड़ा (getActivity ()) से संबंधित है। यदि इस तरह की विधि गतिविधि में नहीं मिली है, तो सिस्टम एक अपवाद फेंक देगा।


धन्यवाद, किसी और ने यह नहीं बताया कि दुर्घटना क्यों हुई थी

1

आप विघटित घटनाओं के लिए EventBus का उपयोग करने पर विचार करना चाह सकते हैं .. आप बहुत आसानी से घटनाओं के लिए सुन सकते हैं। आप यह भी सुनिश्चित कर सकते हैं कि इवेंट ui थ्रेड पर प्राप्त हो रहा है (बजाय runOnUiThread को कॉल करने के लिए .. अपने इवेंट सब्सक्रिप्शन के लिए खुद के लिए)

https://github.com/greenrobot/EventBus

गितुब से:

Android अनुकूलित ईवेंट बस जो गतिविधियों, फ़्रैगमेंट्स, थ्रेड्स, सर्विसेज आदि के बीच संचार को आसान बनाता है, कम कोड, बेहतर गुणवत्ता


1

मैं Adjorn Linkz के जवाब में जोड़ना चाहूंगा ।

यदि आपको कई हैंडलर की जरूरत है, तो आप सिर्फ लैम्ब्डा संदर्भ का उपयोग कर सकते हैं

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

यहां ट्रिक यह है कि handlerविधि का हस्ताक्षर हस्ताक्षर से मेल खाता View.OnClickListener.onClickहै। इस तरह, आपको View.OnClickListenerइंटरफ़ेस की आवश्यकता नहीं होगी ।

इसके अलावा, आपको किसी भी स्विच स्टेटमेंट की आवश्यकता नहीं होगी।

अफसोस की बात है, यह विधि केवल उन इंटरफेस तक सीमित है जिनके लिए एकल विधि, या लंबोदर की आवश्यकता होती है।


1

हालाँकि, मैंने डेटा बाइंडिंग पर भरोसा करते हुए कुछ अच्छे उत्तर दिए हैं, लेकिन मैंने एक्सएमएल में खंड-मुक्त लेआउट परिभाषाओं की अनुमति देते हुए टुकड़े के संकल्प को सक्षम करने के अर्थ में - उस दृष्टिकोण के साथ पूर्ण सीमा तक नहीं देखा।

बंधन मानते हुए डेटा तो है सक्षम है, तो यहाँ एक सामान्य समाधान मेरा प्रस्ताव कर सकता है; थोड़ा लंबा लेकिन यह निश्चित रूप से काम करता है (कुछ केवेट के साथ):

चरण 1: कस्टम ऑनक्लिक कार्यान्वयन

यह टेप-ऑन व्यू (उदाहरण के लिए बटन) से जुड़े संदर्भों के माध्यम से एक खंड-जागरूक खोज चलाएगा:


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

नोट: शिथिल मूल एंड्रॉयड कार्यान्वयन पर आधारित है (देखें https://android.googlesource.com/platform/frameworks/base/+/a175a5b/core/java/android/view/View.java#3025 )

चरण 2: लेआउट फ़ाइलों में घोषणात्मक अनुप्रयोग

फिर, एक्सएमएल के डेटा बाध्यकारी बंधन में:

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

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

चेतावनियां

  • 'आधुनिक' FragmentActivityआधारित कार्यान्वयन मानता है
  • स्टैक में केवल "टॉप-मोस्ट" (यानी अंतिम ) टुकड़े की विधि खोज सकते हैं (हालांकि यह तय किया जा सकता है, अगर जरूरत हो तो)

0

यह मेरे लिए काम कर रहा है: (एंड्रॉयड स्टूडियो)

 @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


0

सबसे अच्छा समाधान IMHO:

टुकड़े में:

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

तब Fragment के onViewStateRestored में:

addClick(R.id.myButton);

0

आपकी गतिविधि कॉलबैक प्राप्त कर रही है जैसा कि उपयोग किया जाना चाहिए:

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

यदि आप चाहते हैं कि आपका टुकड़ा कॉलबैक प्राप्त करे तो ऐसा करें:

mViewPagerCloth.setOnClickListener(this);

और onClickListenerफ्रेगमेंट पर इंटरफ़ेस लागू करें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.