Android Fragment onClick बटन विधि


90

मैं अपने onClick (देखें v) XML में विधि को लागू करने की कोशिश कर रहा हूं, लेकिन Fragment के साथ काम नहीं करता। यह त्रुटि है।

01-17 12:38:36.840: E/AndroidRuntime(4171): java.lang.IllegalStateException: 
Could not find a method insertIntoDb(View) in the activity class main.MainActivity 
for onClick handler on view class android.widget.Button with id 'btn_conferma'

जावा कोड:

public void insertIntoDb(View v) {
...
} 

एक्सएमएल:

<Button
        android:id="@id/btn_conferma"
        style="?android:attr/borderlessButtonStyle"
        android:layout_width="0.0dip"
        android:layout_height="45dp"
        android:layout_marginLeft="2dp"
        android:layout_weight="1.0"
        android:background="@drawable/bottoni"
        android:gravity="center_horizontal|center_vertical"
        android:onClick="insertIntoDb"
        android:text="SALVA"
        android:textColor="#ffffff"
        android:textSize="16sp" />

1
कृपया स्टैकट्रेस और प्रासंगिक कोड के अधिक पोस्ट करें
इमैनुएल

2
जैसा कि यहां कहा गया है। developer.android.com/guide/topics/ui/controls/… , "लेआउट को होस्ट करने वाली गतिविधि को तब संबंधित विधि को लागू करना चाहिए।" आपके मामले में, आपने अपने टुकड़े में संगत विधि लागू की है। इस वजह से, यह IllegalStateException को फेंकता है क्योंकि यह गतिविधि में संबंधित विधि नहीं खोज सका। हो सकता है, आप एक चाल के रूप में इस पोस्ट में दिखाया गया आवेदन कर सकते हैं stackoverflow.com/a/6271637/2515815
hcelaloner

विधि सम्मिलित करें IntoDb (दृश्य) मुख्य होना चाहिए। मुख्यता और फ़्रैगमेंट वर्ग में नहीं।
१cs

सबसे अच्छा समाधान stackoverflow.com/questions/7570575/…
AndroidGeek

जवाबों:


185

आपकी गतिविधि होनी चाहिए

public void insertIntoDb(View v) {
...
} 

खुशबू नहीं।

यदि आप गतिविधि में उपरोक्त नहीं चाहते हैं। टुकड़े में प्रारंभिक बटन और उसी के लिए श्रोता सेट करें।

<Button
    android:id="@+id/btn_conferma" // + missing

फिर

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

   View view = inflater.inflate(R.layout.fragment_rssitem_detail,
    container, false);
   Button button = (Button) view.findViewById(R.id.btn_conferma);
   button.setOnClickListener(new OnClickListener()
   {
             @Override
             public void onClick(View v)
             {
                // do something
             } 
   }); 
   return view;
}

यह मेरे प्रोजेक्ट में क्रैश का कारण बनता है जो एपीआई 21 का उपयोग करता है। कोई वैकल्पिक सुधार / सुझाव?
डार्थ कोडर

@DarthCoder मुझे ऐसा नहीं लगता। आपको कोड प्रस्तुत करना होगा। हो सकता है कि यह इस पोस्ट से संबंधित न हो
रघुनंदन

@ शानू का लॉलीपॉप प्री लॉलीपॉप से ​​कोई लेना देना नहीं है। विवरण के साथ एक और सवाल पोस्ट करें ..
रघुनंदन

जब मैं ऊपर दिए गए उत्तर के रूप में करता हूं, तो क्लिक इवेंट कभी ट्रिगर नहीं होता है।
टेड

3
उपरोक्त टिप्पणियों से मैं थोड़ा हैरान हूं। कोई अपराध नहीं, लेकिन सिर्फ यह कहना कि "यह काम नहीं करता है" बिना किसी विवरण के पोस्ट करना बहुत ही अव्यवसायिक है ... और मेरे लिए, "यह सिर्फ काम करता है"।
झेंग्ग

15

एक अन्य विकल्प यह हो सकता है कि आपके टुकड़े का क्रियान्वयन View.OnClickListener हो और आपके टुकड़े के भीतर onClick (View v) को ओवरराइड करें। यदि आपको गतिविधि के बारे में बात करने की आवश्यकता है, तो बस वांछित विधि के साथ एक इंटरफ़ेस जोड़ें और गतिविधि को लागू करें और इसकी विधि (ओं) को ओवरराइड करें।

public class FragName extends Fragment implements View.OnClickListener { 
    public FragmentCommunicator fComm;
    public ImageButton res1, res2;
    int c;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_test, container, false);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            fComm = (FragmentCommunicator) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement FragmentCommunicator");
        }
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        res1 = (ImageButton) getActivity().findViewById(R.id.responseButton1);
        res1.setOnClickListener(this);
        res2 = (ImageButton) getActivity().findViewById(R.id.responseButton2);
        res2.setOnClickListener(this);
    }
    public void onClick(final View v) { //check for what button is pressed
            switch (v.getId()) {
                case R.id.responseButton1:
                  c *= fComm.fragmentContactActivity(2);
                  break;
                case R.id.responseButton2:
                  c *= fComm.fragmentContactActivity(4);
                  break;
                default:
                  c *= fComm.fragmentContactActivity(100);
                  break;
    }
    public interface FragmentCommunicator{
        public int fragmentContactActivity(int b);
    }



public class MainActivity extends FragmentActivity implements FragName.FragmentCommunicator{
    int a = 10;
    //variable a is update by fragment. ex. use to change textview or whatever else you'd like.

    public int fragmentContactActivity(int b) {
        //update info on activity here
        a += b;
        return a;
    }
}

http://developer.android.com/training/basics/firstapp/starting-activity.html http://developer.android.com/training/basics/fragments/communicating.html


3
मैं हर समय ऐसा करता हूं, लेकिन फिर भी लगता है कि यह बदसूरत है
अलेक्जेंडर फार्बर

मैंने पहले भी किया था, लेकिन अब यह लगभग दूसरा हाथ बन गया है; प्लस यह वास्तव में और अधिक जटिल एप्लिकेशन में मदद करता है लेकिन कुछ बुनियादी के लिए यह ओवरकिल प्रतीत होता है।
cjayem13

@ cjayem13, क्या आप विस्तृत कर सकते हैं "यह एक ओवरकिल क्यों है"?
eRaisedToX

9

यह एक मुद्दा नहीं है, यह एंड्रॉइड का एक डिज़ाइन है। यहाँ देखें :

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

आपकी मेनऐक्टिविटी में कुछ इस तरह से काम करना संभव होगा:

Fragment someFragment;    

...onCreate etc instantiating your fragments

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

और फिर अपने फ्रैगमेंट क्लास में:

public void myClickMethod(View v){
    switch(v.getid()){
       // Your code here
    }
 } 

4

दूसरों ने पहले ही कहा है कि ऑनक्लिक में विधियाँ गतिविधियों में खोजी जाती हैं, टुकड़ों में नहीं। फिर भी, यदि आप वास्तव में चाहते हैं, तो यह संभव है।

मूल रूप से, प्रत्येक दृश्य में एक टैग (शायद अशक्त) होता है। हमने उस दृश्य को भड़काने वाले मूल दृश्य का टैग सेट किया है। फिर, देखने वाले माता-पिता की खोज करना और क्लिक किए गए बटन वाले टुकड़े को पुनः प्राप्त करना आसान है। अब, हम विधि नाम का पता लगाते हैं और उसी खंड को पुनर्प्राप्त खंड से कॉल करने के लिए प्रतिबिंब का उपयोग करते हैं। आसान!

एक कक्षा में जो फैली हुई है Fragment:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_id, container, false);

    OnClickFragments.registerTagFragment(rootView, this); // <========== !!!!!

    return rootView;
}

public void onButtonSomething(View v) {
    Log.d("~~~","~~~ MyFragment.onButtonSomething");
    // whatever
}

सभी गतिविधियाँ समान ButtonHandlingActivity से ली गई हैं:

public class PageListActivity extends ButtonHandlingActivity

ButtonHandlingActivity.java:

public class ButtonHandlingActivity extends Activity {

    public void onButtonSomething(View v) {
        OnClickFragments.invokeFragmentButtonHandlerNoExc(v);
//or, if you want to handle exceptions:
//      try {
//          OnClickFragments.invokeFragmentButtonHandler(v);
//      } catch ...
    }

}

यह सभी xml onClick हैंडलर के लिए विधियों को परिभाषित करना है।

com / उदाहरण / customandroid / OnClickFragments.java:

package com.example.customandroid;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.app.Fragment;
import android.view.View;

public abstract class OnClickFragments {
    public static class FragmentHolder {
        Fragment fragment;
        public FragmentHolder(Fragment fragment) {
            this.fragment = fragment;
        }
    }
    public static Fragment getTagFragment(View view) {
        for (View v = view; v != null; v = (v.getParent() instanceof View) ? (View)v.getParent() : null) {
            Object tag = v.getTag();
            if (tag != null && tag instanceof FragmentHolder) {
                return ((FragmentHolder)tag).fragment;
            }
        }
        return null;
    }
    public static String getCallingMethodName(int callsAbove) {
        Exception e = new Exception();
        e.fillInStackTrace();
        String methodName = e.getStackTrace()[callsAbove+1].getMethodName();
        return methodName;
    }
    public static void invokeFragmentButtonHandler(View v, int callsAbove) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException {
        String methodName = getCallingMethodName(callsAbove+1);
        Fragment f = OnClickFragments.getTagFragment(v);
        Method m = f.getClass().getMethod(methodName, new Class[] { View.class });
        m.invoke(f, v);
    }
    public static void invokeFragmentButtonHandler(View v) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException {
        invokeFragmentButtonHandler(v,1);
    }
    public static void invokeFragmentButtonHandlerNoExc(View v) {
        try {
            invokeFragmentButtonHandler(v,1);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
    public static void registerTagFragment(View rootView, Fragment fragment) {
        rootView.setTag(new FragmentHolder(fragment));
    }
}

और अगले साहसिक कार्य की भविष्यवाणी की जाएगी ...

पुनश्च

यह निश्चित रूप से आप पर निर्भर है कि आप अपने एप्लिकेशन को डिजाइन करें ताकि डेटा एक्टिविटी या फ्रैगमेंट्स (जो MVC से कंट्रोलर , मॉडल-व्यू-कंट्रोलर पॉइंट ऑफ व्यू) के बजाय मॉडल में रहते हैं । देखें आप एक्सएमएल के माध्यम से क्या परिभाषित, प्लस कस्टम दृश्य वर्गों (यदि आप उन्हें परिभाषित करते हैं, अधिकांश लोग बस का पुन: उपयोग पहले से ही है क्या) है। अंगूठे का एक नियम: यदि कुछ डेटा को निश्चित रूप से स्क्रीन मोड़ से बचना चाहिए, तो वे मॉडल से संबंधित हैं ।


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

    View view = inflater.inflate(R.layout.writeqrcode_main, container, false);
    // Inflate the layout for this fragment

    txt_name = (TextView) view.findViewById(R.id.name);
    txt_usranme = (TextView) view.findViewById(R.id.surname);
    txt_number = (TextView) view.findViewById(R.id.number);
    txt_province = (TextView) view.findViewById(R.id.province);
    txt_write = (EditText) view.findViewById(R.id.editText_write);
    txt_show1 = (Button) view.findViewById(R.id.buttonShow1);

    txt_show1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.e("Onclick","Onclick");

            txt_show1.setVisibility(View.INVISIBLE);
            txt_name.setVisibility(View.VISIBLE);
            txt_usranme.setVisibility(View.VISIBLE);
            txt_number.setVisibility(View.VISIBLE);
            txt_province.setVisibility(View.VISIBLE);
        }
    });
    return view;
}

आप ठीक हो !!!!


3
क्या आप बता सकते हैं कि यह सवाल का जवाब कैसे देता है? आखिर में आपकी सजा का क्या मतलब है?
टेपेइमम

2

Kotlin उपयोगकर्ताओं के लिए:

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?, 
    savedInstanceState: Bundle?) : View?
{
    // Inflate the layout for this fragment
    var myView = inflater.inflate(R.layout.fragment_home, container, false)
    var btn_test = myView.btn_test as Button
    btn_test.setOnClickListener {
        textView.text = "hunny home fragment"
    }

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