片段活动捕获onKeyDown并在片段中使用

Flo*_*inD 26 android fragment onkeydown android-activity

我有寻呼机的片段活动:

List<Fragment> fragments = new Vector<Fragment>();
    fragments.add(Fragment.instantiate(this, PastEventListFragment.class.getName(),bundle));
    fragments.add(Fragment.instantiate(this, EventListFragment.class.getName(),bundle));

    this.mPagerAdapter  = new EventPagerAdapter(super.getSupportFragmentManager(), fragments);
    //
    ViewPager pager = (ViewPager)super.findViewById(R.id.viewpager1);

    pager.setAdapter(this.mPagerAdapter);
    pager.setCurrentItem(1);
Run Code Online (Sandbox Code Playgroud)

我赶上了KeyDown事件:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_MENU) {

    }
    return super.onKeyDown(keyCode, event);
}
Run Code Online (Sandbox Code Playgroud)

问题是:如何在我在此活动中实例化的所有片段中使用事件.谢谢

waq*_*lam 33

您可以做的是在片段类中定义自定义方法.例如:

public void myOnKeyDown(int key_code){
   //do whatever you want here
}
Run Code Online (Sandbox Code Playgroud)

每当在Activity类中引发key-down事件时调用此方法.例如:

@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);
}
Run Code Online (Sandbox Code Playgroud)

  • 紧耦合!EW. (13认同)
  • @JonWillis随意提供更好的解决方案 (5认同)
  • `fragment`是什么意思,你声明了什么? (3认同)
  • 实际上,您可以使用接口LocalBroadcast或仅使用EventBus并将使用KeyEvent的KeyEvent发送给任何需要它的人。 (2认同)

PKA*_*KAP 8

如果某人有兴趣如何使用Boradcast:

在onViewCreated中的片段中

@Override
public void onViewCreated(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,
 new IntentFilter("activity-says-hi"));

...}

 // Our handler for received Intents. This will be called whenever an Intent
 // with an action named "custom-event-name" is broadcasted.
 private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
 @Override
 public void onReceive(Context context, Intent intent) {
 // Get extra data included in the Intent

 doSomethingCauseVolumeKeyPressed();

 }
};
Run Code Online (Sandbox Code Playgroud)

你的keyevent - 放入活动的代码

@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();
            }
            return true;
        case KeyEvent.KEYCODE_VOLUME_DOWN:
            if (action == KeyEvent.ACTION_DOWN) {
                sendBroadcast();
            }
            return true;
        default:
            return super.dispatchKeyEvent(event);
    }
}
Run Code Online (Sandbox Code Playgroud)

你的广播发件人:

private void  sendVolumeBroadcast(){
    Intent intent = new Intent("activity-says-hi");
    LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这个解决方案。耦合比标记为正确的耦合少。谢谢! (2认同)

dnh*_*yde 7

按照@hsu.tw 的回答以避免紧密耦合,我发现了这个要点

避免紧密耦合是有代价的:你需要一个可聚焦的视图(幸运的是,这是我的情况,因为我已经在前台有一个监听其他触摸事件的视图,所以我只是添加了它View.OnKeyListener)。

View.OnKeyListener将 a 附加到独立于 Activity 的 Fragment 中的视图所需的步骤是(检查要点):

 view.setFocusableInTouchMode(true);
 view.requestFocus();
 view.setOnKeyListener(pressKeyListener);
Run Code Online (Sandbox Code Playgroud)

我在onViewCreated我的片段的回调中实现了这个


小智 5

正如其他人所提到的,接受的答案导致活动与其片段之间的紧密耦合。

我建议改用某种基于事件的实现。这更具可重用性,并产生更好的软件架构。在以前的项目中,我使用了以下解决方案之一(Kotlin):

广播

使用 Android 的 LocalBroadcastManager:文档

创建一个广播接收器:

class SomeBroadcastReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context?, intent: Intent?) {
        val keyCode = intent?.getIntExtra("KEY_CODE", 0)
        // Do something with the event
    }
Run Code Online (Sandbox Code Playgroud)

}

在您的活动中:

class SomeActivity : AppCompatActivity() {

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        val intent = Intent("SOME_TAG").apply { putExtra("KEY_CODE", keyCode) }
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
        return super.onKeyDown(keyCode, event)
    }

}
Run Code Online (Sandbox Code Playgroud)

然后,在任何片段(或服务等)中:

class SomeFragment : Fragment() {

    val receiver = SomeBroadcastReceiver()

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {

        val filter = IntentFilter().apply { addAction("SOME_TAG") }
        LocalBroadcastManager.getInstance(context!!).registerReceiver(receiver, filter)

        return super.onCreateView(inflater, container, savedInstanceState)
    }

}
Run Code Online (Sandbox Code Playgroud)

事件总线

使用事件总线

创建事件类:

data class Event(val keyCode: Int)
Run Code Online (Sandbox Code Playgroud)

在您的活动中:

class SomeActivity : AppCompatActivity() {

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        EventBus.getDefault().post(Event(keyCode))
        return super.onKeyDown(keyCode, event)
    }

}
Run Code Online (Sandbox Code Playgroud)

然后,在您的片段中:

class SomeFragment : Fragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {

        // Register for events
        EventBus.getDefault().register(this)

        return super.onCreateView(inflater, container, savedInstanceState)
    }

    @Subscribe
    public fun onKeyEvent(event : Event) {
        // Called by eventBus when an event occurs
    }

    override fun onDestroyView() {
        super.onDestroyView()
        EventBus.getDefault().unregister(this)
    }

}
Run Code Online (Sandbox Code Playgroud)