我有寻呼机的片段活动:
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);
我抓住了onKeyDown事件:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU) {
}
return super.onKeyDown(keyCode, event);
}
问题是: 如何在我在此活动中实例化的所有片段中使用事件。感谢
答案 0 :(得分:32)
您可以做的是在片段类中定义自定义方法。例如:
public void myOnKeyDown(int key_code){
//do whatever you want here
}
并在Activity类中引发按键事件时调用此方法。例如:
@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);
}
答案 1 :(得分:7)
如果某人有兴趣如何使用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();
}
};
你的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);
}
}
您的广播发件人:
private void sendVolumeBroadcast(){
Intent intent = new Intent("activity-says-hi");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
答案 2 :(得分:2)
正如其他人所提到的那样,被接受的答案导致活动与其片段之间紧密耦合。
我建议改用某种基于事件的实现。这具有更高的可重用性,并导致更好的软件体系结构。在以前的项目中,我使用了以下解决方案之一(Kotlin):
使用Android的LocalBroadcastManager:Documentation
创建一个BroadcastReceiver:
class SomeBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val keyCode = intent?.getIntExtra("KEY_CODE", 0)
// Do something with the event
}
}
在您的活动中:
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)
}
}
然后,在任何片段(或服务等)中:
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)
}
}
使用EventBus
创建事件类:
data class Event(val keyCode: Int)
在您的活动中:
class SomeActivity : AppCompatActivity() {
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
EventBus.getDefault().post(Event(keyCode))
return super.onKeyDown(keyCode, event)
}
}
然后,在您的片段中:
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)
}
}
答案 3 :(得分:1)
我已经将Activity和Fragment类子类化,以执行KeyEvents传递。对我来说,它看起来比发送本地广播更清晰。但是这个解决方案可能不那么灵活。自己选择首选方式。
以下是活动:
public abstract class KeyEventPassingActivity extends Activity {
public interface KeyEventListener extends View.OnKeyListener {
boolean isVisible();
View getView();
}
private final List<KeyEventListener> keyEventHandlerList = new ArrayList<>();
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
for (KeyEventListener handler : keyEventHandlerList) {
if (handleKeyEvent(handler, event)) {
return true;
}
}
return super.dispatchKeyEvent(event);
}
void addKeyEventHandler(@NonNull KeyEventListener handler) {
keyEventHandlerList.add(handler);
}
void removeKeyEventHandler(@NonNull KeyEventListener handler) {
keyEventHandlerList.remove(handler);
}
/**
* @return <tt>true</tt> if the event was handled, <tt>false</tt> otherwise
*/
private boolean handleKeyEvent(@Nullable KeyEventListener listener, KeyEvent event) {
return listener != null
&& listener.isVisible()
&& listener.onKey(listener.getView(), event.getKeyCode(), event);
}
}
片段:
public abstract class KeyEventHandlingFragment extends Fragment
implements KeyEventPassingActivity.KeyEventListener {
@SuppressWarnings("deprecation")
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof KeyEventPassingActivity) {
((KeyEventPassingActivity) activity).addKeyEventHandler(this);
}
}
@Override
public void onDetach() {
Activity activity = getActivity();
if (activity instanceof KeyEventPassingActivity) {
((KeyEventPassingActivity) activity).removeKeyEventHandler(this);
}
super.onDetach();
}
}
要点:https://gist.github.com/0neel/7d1ed5d26f2148b4168b6616337159ed
答案 4 :(得分:1)
遵循@ hsu.tw答案以避免紧密耦合,我发现了这个gist。
避免紧密耦合需要付出一定的代价:您需要一个可聚焦的视图(幸运的是,我的情况是,因为我已经在前景中监听了其他触摸事件,所以我只添加了View.OnKeyListener
) 。
独立于活动将View.OnKeyListener
附加到片段中的视图所需的步骤是(检查gist):
view.setFocusableInTouchMode(true);
view.requestFocus();
view.setOnKeyListener(pressKeyListener);
我在Fragment的onViewCreated
回调中实现了这一点
答案 5 :(得分:0)
我在开发Android TV应用程序时遇到同样的问题。
我这样解决了这个问题:
在onCreateView方法中,我通过某些View调用“ requestFocus”。 (我将其标记为ViewA。) 然后将KeyEventListener设置为ViewA。
在这种情况下,您应该在Adapter和PagerChangeListener中进行设置(set-KeyEventListener)。