चूँकि यह प्रश्न और उत्तर में से कुछ पाँच साल से अधिक पुराने हैं, मुझे अपना समाधान साझा करने दें। यह @oyenigun से उत्तर के लिए एक अनुवर्ती और आधुनिकीकरण है
अपडेट करें:
इस लेख के निचले भाग में, मैंने एक सार फ्रेगमेंट एक्सटेंशन का उपयोग करते हुए एक वैकल्पिक कार्यान्वयन जोड़ा है जो गतिविधि को बिल्कुल भी शामिल नहीं करेगा, जो किसी भी अधिक जटिल टुकड़े वाले पदानुक्रम के साथ उपयोगी होगा जिसमें नेस्टेड टुकड़े शामिल होते हैं जिन्हें अलग-अलग व्यवहार की आवश्यकता होती है।
मुझे इसे लागू करने की आवश्यकता थी क्योंकि मेरे द्वारा उपयोग किए जाने वाले कुछ अंशों में छोटे दृश्य होते हैं, जिन्हें मैं बैक बटन के साथ खारिज करना चाहता हूं, जैसे कि छोटे जानकारी वाले दृश्य जो पॉप अप करते हैं, आदि, लेकिन यह उन लोगों के लिए अच्छा है जिन्हें व्यवहार को ओवरराइड करने की आवश्यकता है टुकड़े के अंदर वापस बटन।
सबसे पहले, एक इंटरफ़ेस परिभाषित करें
public interface Backable {
boolean onBackPressed();
}
यह इंटरफ़ेस, जिसे मैं कॉल करता हूं Backable
(मैं नामकरण परंपराओं के लिए एक स्टिकर हूं), एक एकल विधि है onBackPressed()
जिसे एक boolean
मूल्य वापस करना होगा । हमें बूलियन मान लागू करने की आवश्यकता है क्योंकि हमें यह जानना होगा कि बैक बटन प्रेस ने बैक ईवेंट को "अवशोषित" कर लिया है या नहीं। लौटने का true
मतलब है कि यह है, और आगे की कार्रवाई की आवश्यकता नहीं है, अन्यथा, false
कहते हैं कि डिफ़ॉल्ट बैक कार्रवाई अभी भी होनी चाहिए। यह इंटरफ़ेस स्वयं की फ़ाइल होना चाहिए (अधिमानतः एक अलग पैकेज में जिसका नाम है interfaces
)। याद रखें, अपनी कक्षाओं को पैकेज में अलग करना अच्छा अभ्यास है।
दूसरा, शीर्ष खंड का पता लगाएं
मैंने एक विधि बनाई जो पिछली Fragment
वस्तु को पीछे के स्टैक में लौटाती है । मैं टैग का उपयोग करता हूं ... यदि आप आईडी का उपयोग करते हैं, तो आवश्यक परिवर्तन करें। मेरे पास एक उपयोगिता वर्ग में यह स्थिर विधि है जो नेविगेशन राज्यों आदि से संबंधित है ... लेकिन निश्चित रूप से, इसे उस जगह पर रखें जहां यह आपको सबसे अच्छा लगता है। संपादन के लिए, मैंने अपना नाम एक वर्ग में रखा NavUtils
।
public static Fragment getCurrentFragment(Activity activity) {
FragmentManager fragmentManager = activity.getFragmentManager();
if (fragmentManager.getBackStackEntryCount() > 0) {
String lastFragmentName = fragmentManager.getBackStackEntryAt(
fragmentManager.getBackStackEntryCount() - 1).getName();
return fragmentManager.findFragmentByTag(lastFragmentName);
}
return null;
}
सुनिश्चित करें कि बैक स्टैक काउंट 0 से अधिक है, अन्यथा ArrayOutOfBoundsException
रनटाइम पर फेंका जा सकता है। यदि यह 0 से अधिक नहीं है, तो अशक्त लौटें। हम बाद में एक शून्य मान के लिए जाँच करेंगे ...
तीसरा, एक टुकड़े में लागू करना
Backable
जहाँ भी आपको बैक बटन के व्यवहार को ओवरराइड करने की आवश्यकता हो , इंटरफ़ेस को लागू करें। कार्यान्वयन विधि जोड़ें।
public class SomeFragment extends Fragment implements
FragmentManager.OnBackStackChangedListener, Backable {
...
@Override
public boolean onBackPressed() {
// Logic here...
if (backButtonShouldNotGoBack) {
whateverMethodYouNeed();
return true;
}
return false;
}
}
में onBackPressed()
ओवरराइड, जो कुछ भी तर्क की जरूरत है डाल दिया। यदि आप चाहते हैं कि बैक बटन बैक स्टैक (डिफ़ॉल्ट व्यवहार) को पॉप न करे , तो सही लौटें , कि आपकी बैक ईवेंट को अवशोषित कर लिया गया है। नहीं तो झूठा लौट आता है।
अंत में, आपकी गतिविधि में ...
onBackPressed()
विधि को ओवरराइड करें और इस तर्क को इसमें जोड़ें:
@Override
public void onBackPressed() {
// Get the current fragment using the method from the second step above...
Fragment currentFragment = NavUtils.getCurrentFragment(this);
// Determine whether or not this fragment implements Backable
// Do a null check just to be safe
if (currentFragment != null && currentFragment instanceof Backable) {
if (((Backable) currentFragment).onBackPressed()) {
// If the onBackPressed override in your fragment
// did absorb the back event (returned true), return
return;
} else {
// Otherwise, call the super method for the default behavior
super.onBackPressed();
}
}
// Any other logic needed...
// call super method to be sure the back button does its thing...
super.onBackPressed();
}
हमें बैक स्टैक में वर्तमान टुकड़ा मिलता है, फिर हम एक अशक्त जांच करते हैं और निर्धारित करते हैं कि क्या यह हमारे Backable
इंटरफ़ेस को लागू करता है। यदि ऐसा होता है, तो निर्धारित करें कि क्या घटना को अवशोषित किया गया था। यदि हां, तो हम कर रहे हैं onBackPressed()
और वापस आ सकते हैं। अन्यथा, इसे एक सामान्य बैक प्रेस के रूप में मानें और सुपर विधि को कॉल करें।
दूसरा विकल्प गतिविधि को शामिल नहीं करना है
कभी-कभी, आप नहीं चाहते कि गतिविधि इसे पूरी तरह से संभाल ले, और आपको इसे सीधे खंडन में संभालना होगा। लेकिन कौन कहता है कि तुम नहीं कर सकते एक बैक प्रेस एपीआई के साथ टुकड़े ? बस एक नए वर्ग के लिए अपने टुकड़े का विस्तार करें।
एक अमूर्त वर्ग बनाएँ, जो फ़्रैगमेंट का विस्तार करता है और View.OnKeyListner
इंटरफ़ेस को लागू करता है ...
import android.app.Fragment;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
public abstract class BackableFragment extends Fragment implements View.OnKeyListener {
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.setFocusableInTouchMode(true);
view.requestFocus();
view.setOnKeyListener(this);
}
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
onBackButtonPressed();
return true;
}
}
return false;
}
public abstract void onBackButtonPressed();
}
जैसा कि आप देख सकते हैं, कोई भी टुकड़ा जो विस्तार BackableFragment
करता है, View.OnKeyListener
इंटरफ़ेस का उपयोग करके स्वचालित रूप से क्लिक पर कब्जा कर लेगा । बस वापस बटन प्रेस करने के लिए मानक तर्क का उपयोग करके onBackButtonPressed()
कार्यान्वित onKey()
विधि के भीतर से अमूर्त विधि को कॉल करें । यदि आपको बैक बटन के अलावा अन्य कुंजी क्लिकों को पंजीकृत करने की आवश्यकता है, super
तो onKey()
अपने टुकड़े में ओवरराइड करते समय विधि को कॉल करना सुनिश्चित करें , अन्यथा आप इसे हटा देंगे अमूर्त व्यवहार को ।
उपयोग करने के लिए सरल, बस विस्तार और कार्यान्वयन:
public class FragmentChannels extends BackableFragment {
...
@Override
public void onBackButtonPressed() {
if (doTheThingRequiringBackButtonOverride) {
// do the thing
} else {
getActivity().onBackPressed();
}
}
...
}
चूंकि onBackButtonPressed()
सुपर क्लास में विधि अमूर्त है, एक बार जब आप विस्तार करते हैं तो आपको इसे लागू करना होगा onBackButtonPressed()
। यह लौटता है void
क्योंकि इसे केवल खंड वर्ग के भीतर एक क्रिया करने की आवश्यकता होती है, और गतिविधि में वापस प्रेस के अवशोषण को रिले करने की आवश्यकता नहीं होती है। सुनिश्चित करें कि आप गतिविधि onBackPressed()
विधि को कॉल करते हैं यदि आप बैक बटन के साथ जो कुछ भी कर रहे हैं उसे संभालने की आवश्यकता नहीं है, अन्यथा, बैक बटन अक्षम हो जाएगा ... और आप ऐसा नहीं चाहते हैं!
कैविट्स
जैसा कि आप देख सकते हैं, यह प्रमुख श्रोता को खंड के मूल दृश्य पर सेट करता है, और हमें इसे ध्यान केंद्रित करने की आवश्यकता होगी। यदि आपके खंड में शामिल ग्रंथों (या किसी अन्य फ़ोकस-चोरी दृश्य) को शामिल किया गया है जो इस वर्ग को बढ़ाता है, (या अन्य आंतरिक टुकड़े या विचार जो समान हैं), आपको अलग से संभालना होगा। बैक प्रेस पर फ़ोकस खोने के लिए एक EditText का विस्तार करने पर एक अच्छा लेख है ।
मुझे आशा है कि किसी को यह उपयोगी लगता है। खुश कोडिंग।