美文网首页程序员@IT·互联网
在安卓ActionBar上用纯JAVA代码添加搜索栏的经验心得

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

作者: 秋灏未央 | 来源:发表于2017-05-03 17:41 被阅读0次

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

    最近很喜欢“胜天半子”,故引用原文结尾作为本篇开头,也勉励自己。上周的安卓开发遇到在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代码添加搜索栏的经验心得

        本文链接:https://www.haomeiwen.com/subject/ojfqtxtx.html