在安卓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()是我自定义的方法。一个是用来刷新页面,一个是移除现在的页面(因为我们要添加搜索得到的页面)。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容