在安卓ActionBar上用纯JAVA代码添加搜索栏的经验心得

众人登山围拢教师,见他异样神情皆不解。纷纷问道:“你看什么?浑沌干啥?”教师答:“下棋。”“深山旷野,与谁下棋?”教师沉默不语。良久,沉甸甸道出一字:“天!”
俗人浅见,喳喳追问:“赢了还是输了?”
教师细细数目。数至右下角,见到那个决定胜负的劫。浑沌长跪于地,充当一枚黑子,恰恰劫胜!教师崇敬浑沌精神,激情澎湃。他双手握拳冲天高举,喊得山野震荡,林木悚然——
“胜天半子!”

最近很喜欢“胜天半子”,故引用原文结尾作为本篇开头,也勉励自己。上周的安卓开发遇到在ActionBar上添加搜索栏的问题,然而现在Toolbar大行其道,导致这方面的资源比较少,所以我花了很大的力气慢慢调教。以下是自己的一点心得。

ActionBar是比较老的组件,不能支持SearchView,所以我选择了EditView作为我搜索栏的Search Bar。因为一些身不由己的原因只能使用ActionBar的同学们,一定是能感同身受我只能选择EditView的纠结的 :( 。作为一个完整的搜索栏,Search Bar里的清空按钮和整个搜索栏的推出按钮也是必不可少的。以下是我用纯JAVA代码写的整个搜索栏的样子:

整个搜索栏放在一个LinearLayout里

//ADD A SEARCH HEADER INSTEAD OF THE OLD HEADER, AFTER CLICKING SEARCH BUTTON
        LinearLayout searchHeader = new LinearLayout(context);
        searchHeader.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        searchHeader.setOrientation(LinearLayout.HORIZONTAL);
        searchHeader.setBackgroundColor(Color.BLACK);
        searchHeader.setVisibility(View.GONE);

在这之前我有个搜索图标设置了点击跳转搜索栏的功能,很简单我就不放出来了。这里是整个搜索栏的框架,之所以用LinearLayout是因为它可以自动横向排列,比RelativeLayout省去很多布置的代码。
然后就是EditView:

Search Bar

//ADD A SEARCH BAR IN SEARCH HEADER, WHICH SHOWS AFTER CLICKING SEARCH BUTTON
        EditText search = new EditText(mainActivity);
        search.setInputType(InputType.TYPE_CLASS_TEXT);
        search.setSingleLine();
        search.setImeOptions(EditorInfo.IME_ACTION_SEARCH);
        search.setHint("Search");
        //ADD A SEARCH ICON INSIDE THE SEARCH BAR
        Drawable searchIcon = context.getResources().getDrawable(R.drawable.places_ic_search);
        search.setCompoundDrawablesWithIntrinsicBounds(searchIcon, null, null, null);
        LinearLayout.LayoutParams lp2 = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 8);// Create lp for setting up margins
        lp2.setMargins(50, 20, 0, 20);
        search.setLayoutParams(lp2);
        search.setPadding(5, 5, 5, 5);
        search.setBackgroundColor(Color.WHITE);
        search.setTextColor(Color.BLACK);

这里

search.setSingleLine();

search.setImeOptions(EditorInfo.IME_ACTION_SEARCH);

是这个搜索栏能实现功能的关键。其他的都是一下外观上的东西。比如那个Drawable就是一个放大镜的图标,放到搜索栏的最左边。接下来是里面的Clear按钮,负责清楚文本和收回键盘:

Close Button

//ADD A CLOSE BUTTON IN SEARCH HEADER, WHICH SHOWS AFTER CLICKING SEARCH BUTTON
        ImageButton closeButton = new ImageButton(mainActivity);
        closeButton.setBackgroundColor(Color.WHITE);
        closeButton.setColorFilter(Color.GRAY);
        closeButton.setScaleType(ImageView.ScaleType.FIT_CENTER);
        closeButton.setImageResource(R.drawable.delete_filled);
        LinearLayout.LayoutParams lp1 = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1);// Create lp for setting up margins
        lp1.setMargins(0, 20, 0, 20);
        closeButton.setLayoutParams(lp1);
        closeButton.setVisibility(View.GONE);

这里R.drawable.delete_filled是我自定义的图标,大家可以使用ic_delete这种自带图标。最后是关掉整个搜索栏的Cancel按钮:

Cancel Button

 //ADD A CANCEL BUTTON IN SEARCH HEADER, WHICH SHOWS AFTER CLICKING SEARCH BUTTON
        Button cancelButton = new Button(mainActivity);
        String cancelText = "Cancel";
        SpannableString content = new SpannableString(cancelText);
        content.setSpan(new UnderlineSpan(), 0, cancelText.length(), 0);
        cancelButton.setText(content);
        cancelButton.setTypeface(LVATabUtilities.latoRegular);
        cancelButton.setLayoutParams(new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 2));
        cancelButton.setPadding(5, 5, 5, 5);
        cancelButton.setTextColor(Color.parseColor(LVATabUtilities.getAppProperty("HighlightHEX")));
        cancelButton.setBackgroundColor(Color.BLACK);`

为了做得跟IOS像一点,我在文本上加了下划线。
##最后是把他们都放到LinearLayout里面去
`searchHeader.addView(search);
 searchHeader.addView(closeButton);
 searchHeader.addView(cancelButton);

这里还有一点是,因为我用的LinearLayout,所以可以按权重分配各部分的大小,所以上述代码里SearchBar : CloseButton : CancelButton = 8 : 1 : 2。 他们的高度必须是Match_Parent, 宽度既不是Match_Parent也不是Wrap_Content, 而是0。这样做是为了固定他们的大小,而不会因为文本过长导致整个搜索栏变形。这样我们的搜索栏外观就完成了,然而万里长征也才走完了第一步。

接下来是实现这个搜索栏的功能。我们首先从简单的开始。

CloseButton的功能是清空文本和收回键盘

  //ADD CLOSE BUTTON'S FUNCTIONALITY
                closeButton.setVisibility(View.VISIBLE);
                closeButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        search.setText("");
                        closeButton.setVisibility(View.GONE);
                        hideKeyboard();
                    }
                });

CancelButton的功能是收回搜索栏和强制退出键盘

public static void clickOnCancelButton(final Button button, final ImageButton imageButton, final LinearLayout linearLayout){
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                imageButton.setVisibility(View.VISIBLE);
                linearLayout.setVisibility(View.GONE);
                removeFragmentFromCurrentViewPagerTab("SearchView");
                hideSoftKeyboard(button);
            }
        });
    }

上面的removeFragment方法是把我当年搜索所添加的Fragment再关掉,以此达到“关掉搜索界面” :)。怎么remove我就不贴代码了,因为是我们具体的app功能,只要做到这个思想就行了。

这个是自己写的强制退出键盘的方法,和上面CloseButton不同,用系统自带的hideKeyBoard()不能在Cancel时使用。

public static void hideSoftKeyboard(Button button) {
        InputMethodManager imm = (InputMethodManager) mainActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(button.getWindowToken(), 0);
    }

在某个位置调用方法实现功能

//ADD A CLICKLISTENER FOR CANCEL BUTTON, WHICH RETURNS BACK TO NORMAL SCREEM
        clickOnCancelButton(cancelButton, searchButton, searchHeader);

最后就是数据的处理,这需要根据自己的情况量身定做。基本的思路就是找到自己这个Fragment的Adapter,在里面创建一个方法。然后把数据在里面处理了在调用到展示的Fragment页面中来。Adapter里的方法我就不放出来了,也没有参考价值。最后我们需要一个TextWacther监听EditText的所有动作,以下是它的代码:

在EditText中加入TextWatcher

//ADD A TEXTCHANGEDLISTENER FOR SEARCH BAR
        TextWatcher textWatcher = new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                //NOTHING
            }

            @Override
            public void onTextChanged(final CharSequence s, int start, int before, int count) {
                //这里定义SearchView和SearchViewAdapter

                //ADD CLOSE BUTTON'S FUNCTIONALITY
                closeButton.setVisibility(View.VISIBLE);
                closeButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        search.setText("");
                        closeButton.setVisibility(View.GONE);
                        hideKeyboard();
                    }
                });

                //ADD SEARCH'S FUNCTIONALITY
                search.setOnEditorActionListener(new TextView.OnEditorActionListener() {
                    @Override
                    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                    if (actionId == EditorInfo.IME_ACTION_SEARCH) {
                        //这行用定义好的SearchView和SearchViewAdapter写处理数据的代码
                        detachAndAttachCurrentFragment();
                        hideKeyboard();
                        return true;
                    }
                    return false;
                    }
                });

                //REPLACE CURRENT FRAGMENT
                removeFragmentFromCurrentViewPagerTab();
            }

            @Override
            public void afterTextChanged(Editable s) {
                //NOTHING
            }
        };
        search.addTextChangedListener(textWatcher);

这样大体上我们就大功告成啦。这里detachAndAttachCurrentFragment()和removeFragmentFromCurrentViewPagerTab()是我自定义的方法。一个是用来刷新页面,一个是移除现在的页面(因为我们要添加搜索得到的页面)。

你可能感兴趣的:(在安卓ActionBar上用纯JAVA代码添加搜索栏的经验心得)