Fragment Activity Catch Onkeydown And Use In Fragment
Solution 1:
What you can do is to define a custom method in your fragment class(s). For example:
publicvoidmyOnKeyDown(int key_code){
//do whatever you want here
}
and call this method whenever a key-down event is raised in your Activity class. For example:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU) {
((PastEventListFragment)fragments.get(0)).myOnKeyDown(keyCode);
((EventListFragment)fragments.get(1)).myOnKeyDown(keyCode);
//and so on...
}
return super.onKeyDown(keyCode, event);
}
Solution 2:
If someone is interessed how to do it with Boradcast:
In your fragment in onViewCreated
@OverridepublicvoidonViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Register to receive messages.// We are registering an observer (mMessageReceiver) to receive Intents// with actions named "custom-event-name".LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
newIntentFilter("activity-says-hi"));
...}
// Our handler for received Intents. This will be called whenever an Intent// with an action named "custom-event-name" is broadcasted.privateBroadcastReceiver mMessageReceiver = newBroadcastReceiver() {
@OverridepublicvoidonReceive(Context context, Intent intent) {
// Get extra data included in the IntentdoSomethingCauseVolumeKeyPressed();
}
};
your keyevent - code to put in activity
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
int action = event.getAction();
int keyCode = event.getKeyCode();
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_UP:
if (action == KeyEvent.ACTION_DOWN) {
sendBroadcast();
}
returntrue;
case KeyEvent.KEYCODE_VOLUME_DOWN:
if (action == KeyEvent.ACTION_DOWN) {
sendBroadcast();
}
returntrue;
default:
return super.dispatchKeyEvent(event);
}
}
your broadcast sender:
privatevoidsendVolumeBroadcast(){
Intent intent = new Intent("activity-says-hi");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
Solution 3:
As mentioned by others, the accepted answer results in tight coupling between the activity and its fragments.
I would suggest using some sort of event-based implementation instead. This is much more reusable and results in a better software architecture. In previous projects I have used one of the following solutions (Kotlin):
Broadcasts
Using Android´s LocalBroadcastManager: Documentation
Create a BroadcastReceiver:
classSomeBroadcastReceiver : BroadcastReceiver() {
overridefunonReceive(context: Context?, intent: Intent?) {
val keyCode = intent?.getIntExtra("KEY_CODE", 0)
// Do something with the event
}
}
In your activity:
classSomeActivity : AppCompatActivity() {
overridefunonKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
val intent = Intent("SOME_TAG").apply { putExtra("KEY_CODE", keyCode) }
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
returnsuper.onKeyDown(keyCode, event)
}
}
Then, in any of the fragments (or services, etc..):
classSomeFragment : Fragment() {
val receiver = SomeBroadcastReceiver()
overridefunonCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val filter = IntentFilter().apply { addAction("SOME_TAG") }
LocalBroadcastManager.getInstance(context!!).registerReceiver(receiver, filter)
returnsuper.onCreateView(inflater, container, savedInstanceState)
}
}
EventBus
Using EventBus
Create an event class:
dataclassEvent(val keyCode: Int)
In your activity:
classSomeActivity : AppCompatActivity() {
overridefunonKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
EventBus.getDefault().post(Event(keyCode))
returnsuper.onKeyDown(keyCode, event)
}
}
Then, in your fragment:
classSomeFragment : Fragment() {
overridefunonCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Register for events
EventBus.getDefault().register(this)
returnsuper.onCreateView(inflater, container, savedInstanceState)
}
@SubscribepublicfunonKeyEvent(event : Event) {
// Called by eventBus when an event occurs
}
overridefunonDestroyView() {
super.onDestroyView()
EventBus.getDefault().unregister(this)
}
}
Solution 4:
Following @hsu.tw answer to avoid tight coupling I found this gist.
Avoiding tight coupling comes with a price: you need a focusable view (luckily it was my case since I already had a view in foreground that listens to other touch events, so I just added the View.OnKeyListener
to it).
The steps needed to attach a View.OnKeyListener
to a view in a Fragment independently of the Activity are (check the gist):
view.setFocusableInTouchMode(true);
view.requestFocus();
view.setOnKeyListener(pressKeyListener);
I implemented this in the onViewCreated
callback of my Fragment
Solution 5:
I've subclassed Activity and Fragment classes to perform KeyEvents passing. For me, it looks clearer than sending local broadcasts. But this solution can be not so flexible. Choose the preferred way by yourself.
Here is the activity:
publicabstractclassKeyEventPassingActivityextendsActivity {
publicinterfaceKeyEventListenerextendsView.OnKeyListener {
booleanisVisible();
View getView();
}
privatefinal List<KeyEventListener> keyEventHandlerList = newArrayList<>();
@OverridepublicbooleandispatchKeyEvent(KeyEvent event) {
for (KeyEventListener handler : keyEventHandlerList) {
if (handleKeyEvent(handler, event)) {
returntrue;
}
}
returnsuper.dispatchKeyEvent(event);
}
voidaddKeyEventHandler(@NonNull KeyEventListener handler) {
keyEventHandlerList.add(handler);
}
voidremoveKeyEventHandler(@NonNull KeyEventListener handler) {
keyEventHandlerList.remove(handler);
}
/**
* @return <tt>true</tt> if the event was handled, <tt>false</tt> otherwise
*/privatebooleanhandleKeyEvent(@Nullable KeyEventListener listener, KeyEvent event) {
return listener != null
&& listener.isVisible()
&& listener.onKey(listener.getView(), event.getKeyCode(), event);
}
}
And the fragment:
publicabstractclassKeyEventHandlingFragmentextendsFragmentimplementsKeyEventPassingActivity.KeyEventListener {
@SuppressWarnings("deprecation")@OverridepublicvoidonAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof KeyEventPassingActivity) {
((KeyEventPassingActivity) activity).addKeyEventHandler(this);
}
}
@OverridepublicvoidonDetach() {
Activityactivity= getActivity();
if (activity instanceof KeyEventPassingActivity) {
((KeyEventPassingActivity) activity).removeKeyEventHandler(this);
}
super.onDetach();
}
}
Gist: https://gist.github.com/0neel/7d1ed5d26f2148b4168b6616337159ed
Post a Comment for "Fragment Activity Catch Onkeydown And Use In Fragment"