android - XML पर क्लिक करके बटन क्लिक को कैसे प्रबंधित करें Fragments के भीतर क्लिक करें




button android-fragments (12)

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

android:onClick="myClickMethod"

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

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

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

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

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

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

https://github.com/greenrobot/EventBus

गीथूब से:

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


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

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

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


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

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

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

mViewPagerCloth.setOnClickListener(this);

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


जैसा कि मैं जवाब देखता हूं वे किसी भी तरह पुराने हैं। हाल ही में Google डेटा DataBinding पेश करता है जो आपके 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>

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


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

गतिविधि:

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

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

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

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

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

मैं एडजर्न लिंकज़ के answer जोड़ना चाहता हूं।

यदि आपको एकाधिक हैंडलर की आवश्यकता है, तो आप केवल लैम्ब्डा संदर्भों का उपयोग कर सकते हैं

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

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

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

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


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

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

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


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

1. इस तरह एक बेसफ्रैगमेंट बनाएं:

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

आशा करता हूँ की ये काम करेगा।


सर्वश्रेष्ठ समाधान आईएमएचओ:

खंड में:

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

फिर फ्रैगमेंट के ऑनव्यूस्टेटेड में:

addClick(R.id.myButton);

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

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

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

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




android-fragments