【问题标题】:How can I get onBackPressed() while SearchView is activated?激活 SearchView 时如何获取 onBackPressed()?
【发布时间】:2012-11-17 14:01:03
【问题描述】:

如何在搜索模式下处理onBackPressed()?我在ActionBar实现了搜索,我要处理onBackPressed()

编辑:

MainActivity我已经添加了这个,但它只会在搜索关闭时得到通知

@Override
public void onBackPressed() {
    mMenu.findItem(R.id.menu_eye).setVisible(true);
    mMenu.findItem(R.id.menu_layers).setVisible(true);
    super.onBackPressed();  
};

我的搜索操作监听器如下所示:

import com.cyrilmottier.polaris.PolarisMapView;

import android.app.SearchManager.OnCancelListener;
import android.content.Context;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.SearchView;

public class SearchListener implements SearchView.OnQueryTextListener, SearchView.OnCloseListener, SearchView.OnSuggestionListener, OnClickListener, OnCancelListener{

    private Context mContext;
    private PolarisMapView mMapView;
    private Menu mMenu;
    private SearchView mSearchView;

    public SearchListener(Context c, PolarisMapView mMapView, Menu mMenu, SearchView mSearchView){
        this.setmContext(c);
        this.setmMapView(mMapView);
        this.setmMenu(mMenu);
        this.mSearchView = mSearchView;
    }

    @Override
    public boolean onQueryTextChange(String newText) {
        return false;
    }

    @Override
    public boolean onQueryTextSubmit(String query) {
        if (Constants.searchPlaceNavigate(query, mContext, mMapView))
            return this.onClose();
        return false;
    }

    public Context getmContext() {
        return mContext;
    }

    public void setmContext(Context mContext) {
        this.mContext = mContext;
    }

    public PolarisMapView getmMapView() {
        return mMapView;
    }

    public void setmMapView(PolarisMapView mMapView) {
        this.mMapView = mMapView;
    }

    @Override
    public boolean onSuggestionClick(int position) {
        String p = mSearchView.getSuggestionsAdapter().getCursor().getString(position);
        if(position== 0)
            p = mSearchView.getSuggestionsAdapter().getCursor().getString(position*4+1);
        if(p != null)
            if(position== 0)
                Constants.searchPlaceNavigate(mSearchView.getSuggestionsAdapter().getCursor().getString(position*4+1), mContext, mMapView);
            else
                Constants.searchPlaceNavigate(mSearchView.getSuggestionsAdapter().getCursor().getString(position), mContext, mMapView);
        return this.onClose();
    }

    @Override
    public boolean onSuggestionSelect(int position) {

        return false;
    }

    @Override
    public boolean onClose() {
        mMenu.findItem(R.id.menu_eye).setVisible(true);
        mMenu.findItem(R.id.menu_layers).setVisible(true);
        mMenu.findItem(R.id.menu_search).collapseActionView();
        return true;
    }

    public Menu getmMenu() {
        return mMenu;
    }

    public void setmMenu(Menu mMenu) {
        this.mMenu = mMenu;
    }

    public SearchView getmSearchView() {
        return mSearchView;
    }

    public void setmSearchView(SearchView mSearchView) {
        this.mSearchView = mSearchView;
    }

    @Override
    public void onClick(View v) {
        this.onClose();
    }

    @Override
    public void onCancel() {
        this.onClose();

    }

}

【问题讨论】:

  • 我已经更新了我的问题:如何在搜索模式下处理 onBackPressed?

标签: android searchview


【解决方案1】:

重写此方法可能会对您有所帮助

 @Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    // TODO Auto-generated method stub
    return super.onKeyDown(keyCode, event);
}

【讨论】:

  • 我应该将此监听器绑定到什么?主要活动?因为searchview没有setOnKeyDown()方法只有setOnKeyListener
  • but @Override public boolean onKey(View v, int keyCode, KeyEvent event) { // TODO 自动生成的方法存根 return false; } 也不起作用
  • 这不起作用,因为:当一个键被按下并且没有被活动内部的任何视图处理时调用。但是你可以扩展 SearchView 并覆盖它自己的 onKeyDown 方法。
  • 我同意 SearchView 可以扩展以覆盖 onKeyDown()。但是如何将 searchItem.getActionView() 返回的 SearchView 对象转换为扩展类呢?
【解决方案2】:

您始终可以像这样扩展任何视图并覆盖侦听方法:

class MySearchView extends SearchView {
  @Override
  public boolean onKeyDown(int keyCode, KeyEvent event) {
     return super.onKeyDown(keyCode, event); //don't forget call this
  }
}

【讨论】:

  • 扩展时不需要定义默认构造函数吗?公共 MySearchView(上下文上下文){ 超级(上下文); }
  • 是的,你需要定义一个默认的构造函数,这很明显。作为回答,我只写了解决问题的实际代码。
【解决方案3】:

我找到了答案,关键是之前来自 Mr.Ali Imran 和 neworld 的答案 我必须重写这个方法:

@Override
public void onActionViewCollapsed() {
    //do somethink
    super.onActionViewCollapsed();
}

每次关闭searchView时都会调用它,所以它可以处理后退按钮的情况。

【讨论】:

  • 这没有回答问题。当用户按下“主页”箭头(SearchView 左侧的onActionViewCollapsed() 也会触发。
【解决方案4】:

另一种方法是在 MenuItem 上监听 ActionExpand/Collapse :

    MenuItem searchMenuItem = menu.findItem(R.id.menu_search);
    searchMenuItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {

        @Override
        public boolean onMenuItemActionExpand(MenuItem item) {
            // Do whatever you need
            return true; // KEEP IT TO TRUE OR IT DOESN'T OPEN !!
        }

        @Override
        public boolean onMenuItemActionCollapse(MenuItem item) {
            // Do whatever you need
            return true; // OR FALSE IF YOU DIDN'T WANT IT TO CLOSE!
        }
    });
    SearchView searchView = (SearchView) searchMenuItem.getActionView();
    ... // Keep doing as you do

我认为这种方式更干净,因为您可以直接听自己想要的内容

感谢this thread

【讨论】:

    【解决方案5】:

    为了支持旧设备,可以使用以下代码:

            MenuItemCompat.setOnActionExpandListener(searchItem,new MenuItemCompat.OnActionExpandListener() {
    
                @Override
                public boolean onMenuItemActionExpand(MenuItem item) {
                    //Do whatever you want                   
                    return true;
                }
    
                @Override
                public boolean onMenuItemActionCollapse(MenuItem item) {
                    //Do whatever you want
                    return true;
                }
            });
    

    【讨论】:

    • 谢谢!你拯救了我的一天
    • @raheel 只是一个问题,我支持的最低 API 是 14,那为什么我还要使用 MenuItemCompat,我在其他一些论坛上读到,只有在最低 API 级别为14岁以下! .. 但是,谢谢你,它奏效了!
    • 现在已弃用,有人可以更新答案
    【解决方案6】:

    您可以扩展 SearchView 并覆盖 dispatchKeyEventPreIme:

    公共类 CustomSearchView 扩展 SearchView{ 公共CustomSearchView(最终上下文上下文){ 超级(上下文); this.setIconifiedByDefault(true); } @覆盖 公共布尔dispatchKeyEventPreIme(KeyEvent事件){ if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) { this.onActionViewCollapsed(); } return super.dispatchKeyEventPreIme(event); } }

    【讨论】:

    • 我还在this.onActionViewCollapsed() 之后调用this.clearFocus() 否则我最终会在actionBar 的其他地方出现一些奇怪的突出显示
    【解决方案7】:

    与制作自定义搜索视图的答案相同,但带有侦听器

    public class SearchViewer extends SearchView {
        private OnBackPressListener onBackPressListener;
        private boolean isKeyboardVisible;
    
            public SearchViewer(Context context) {
                super(context);
            }
    
            public SearchViewer(Context context, AttributeSet attrs) {
                super(context, attrs);
            }
    
            public SearchViewer(Context context, AttributeSet attrs, int defStyleAttr) {
                super(context, attrs, defStyleAttr);
            }
    
            private void init() {
                KeyboardUtils.addKeyboardToggleListener((Activity) getContext(), new KeyboardUtils.SoftKeyboardToggleListener() {
                    @Override
                    public void onToggleSoftKeyboard(boolean isVisible) {
                        SearchViewer.this.isKeyboardVisible = isVisible;
                    }
                });
    
            }
    
            @Override
            protected void onAttachedToWindow() {
                super.onAttachedToWindow();
                init();
            }
    
            @Override
            protected void onDetachedFromWindow() {
                super.onDetachedFromWindow();
                KeyboardUtils.removeAllKeyboardToggleListeners();
            }
    
            @Override
            public boolean dispatchKeyEventPreIme(KeyEvent event) {
                if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
                    if (onBackPressListener != null && !isKeyboardVisible)
                        onBackPressListener.backPress();
                }
                return super.dispatchKeyEventPreIme(event);
            }
    
            public OnBackPressListener getOnBackPressListener() {
                return onBackPressListener;
            }
    
            public void setOnBackPressListener(OnBackPressListener onBackPressListener) {
                this.onBackPressListener = onBackPressListener;
            }
    
            public interface OnBackPressListener {
                void backPress();
            }
        }
    

    用于键盘可见性的 Util 类,因此如果键盘可见返回 Press 将隐藏它而不关闭活动

    public class KeyboardUtils implements ViewTreeObserver.OnGlobalLayoutListener {
        private static HashMap<SoftKeyboardToggleListener, KeyboardUtils> sListenerMap = new HashMap<>();
        private SoftKeyboardToggleListener mCallback;
        private View mRootView;
        private float mScreenDensity = 1;
        private KeyboardUtils(Activity act, SoftKeyboardToggleListener listener) {
            mCallback = listener;
    
            mRootView = ((ViewGroup) act.findViewById(android.R.id.content)).getChildAt(0);
            mRootView.getViewTreeObserver().addOnGlobalLayoutListener(this);
    
            mScreenDensity = act.getResources().getDisplayMetrics().density;
        }
    
        public static void addKeyboardToggleListener(Activity act, SoftKeyboardToggleListener listener) {
            removeKeyboardToggleListener(listener);
    
            sListenerMap.put(listener, new KeyboardUtils(act, listener));
        }
    
        public static void removeKeyboardToggleListener(SoftKeyboardToggleListener listener) {
            if (sListenerMap.containsKey(listener)) {
                KeyboardUtils k = sListenerMap.get(listener);
                k.removeListener();
    
                sListenerMap.remove(listener);
            }
        }
    
        public static void removeAllKeyboardToggleListeners() {
            for (SoftKeyboardToggleListener l : sListenerMap.keySet())
                sListenerMap.get(l).removeListener();
    
            sListenerMap.clear();
        }
    
        @Override
        public void onGlobalLayout() {
            Rect r = new Rect();
            //r will be populated with the coordinates of your view that area still visible.
            mRootView.getWindowVisibleDisplayFrame(r);
    
            int heightDiff = mRootView.getRootView().getHeight() - (r.bottom - r.top);
            float dp = heightDiff / mScreenDensity;
    
            if (mCallback != null)
                mCallback.onToggleSoftKeyboard(dp > 200);
        }
    
        private void removeListener() {
            mCallback = null;
    
            mRootView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        }
    
        public interface SoftKeyboardToggleListener {
            void onToggleSoftKeyboard(boolean isVisible);
        }
    
    }
    

    示例代码:

    searchView.setOnBackPressListener(new SearchViewer.OnBackPressListener() {
        @Override
        public void backPress() {
            onBackPressed();
        }
    });
    

    【讨论】:

    • 当我在 DialogFragment 中以非常规方式使用 SearchView 时,帮助我完全在默认的 ActionBar 之外使用 setIconifiedByDefault(false);。干杯!
    • 这个解决方案也帮助了我。我在 setOnBackPressListener 中调用 onBackPressed 时遇到问题,因为我的活动中覆盖的 onBackPressed 被调用了两次。如果有人有这个问题,只需在 dispatchKeyEventPreIme 添加这些行 if (onBackPressListener != null &amp;&amp; !isKeyboardVisible) { onBackPressListener.backPress(); return true; }
    【解决方案8】:

    使用此代码处理onBackPressed() 以转到上一个活动

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
    
        int id = item.getItemId();
        switch (id){
            case android.R.id.home:
                onBackPressed();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    
    }
    

    【讨论】:

      【解决方案9】:

      试试这个

          @Override
          public boolean onCreateOptionsMenu(Menu menu) {
      
              getMenuInflater().inflate(R.menu.menu_main, menu);
      
              MenuItem searchItem = menu.findItem(R.id.action_search);
      
              searchItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
              @Override
              public boolean onMenuItemActionExpand(MenuItem item) {
                   //do something here
      
                    return true;
              }
      
              @Override
              public boolean onMenuItemActionCollapse(MenuItem item) {
                  //do something here
                  
                  //YourActivity is acitvity where you define searchview and fragment
                  YourActivity.super.onBackPressed();  //remove fragment from backstack
      
                  return true;
              }
          });
      
          //Any other code
      
      }
      

      onMenuItemActionCollapse(MenuItem item) 将在单击SearchView 的向上按钮或按返回按钮时运行。它将从 backstack 中删除片段。

      【讨论】:

        猜你喜欢
        • 2015-04-23
        • 2016-10-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-13
        • 2016-09-18
        • 2018-04-27
        相关资源
        最近更新 更多