如何在Android

时间:2017-01-09 08:12:08

标签: android android-library android-search

我希望在我的应用程序中将此库用于 searchBar See Link

此库 minSDK 有16个,当在 SDK 16和17 上运行此库并单击EditText(对于写入世界)时,不显示我的任何文本并且只显示白色屏幕(在editText中),但在设备上使用 SDK 18 以及更高版本运行时确定而不是错误!

SearchBar代码:

public class MaterialSearchBar extends RelativeLayout implements View.OnClickListener,
        Animation.AnimationListener, SuggestionsAdapter.OnItemViewClickListener,
        View.OnFocusChangeListener, TextView.OnEditorActionListener {
    public static final int BUTTON_SPEECH = 1;
    public static final int BUTTON_NAVIGATION = 2;

    private LinearLayout inputContainer;
    private ImageView searchIcon;
    private ImageView arrowIcon;
    private AppCompatEditText searchEdit;
    private ImageView navIcon;
    private OnSearchActionListener onSearchActionListener;
    private boolean searchEnabled;
    private boolean suggestionsVisible;
    public static final int VIEW_VISIBLE = 1;
    public static final int VIEW_INVISIBLE = 0;
    private SuggestionsAdapter adapter;
    private float destiny;

    private int searchIconRes;
    private int navIconResId;
    private CharSequence hint;
    private int maxSuggestionCount;
    private boolean speechMode;

    private int menuResource;
    private PopupMenu popupMenu;

    private int textColor;
    private int hintColor;

    private boolean navButtonEnabled;

    public MaterialSearchBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs);
    }

    public MaterialSearchBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public MaterialSearchBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(attrs);
    }

    private void init(AttributeSet attrs) {
        inflate(getContext(), R.layout.searchbar, this);

        TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.MaterialSearchBar);
        searchIconRes = array.getResourceId(R.styleable.MaterialSearchBar_searchIconDrawable, -1);
        navIconResId = array.getResourceId(R.styleable.MaterialSearchBar_navIconDrawable, -1);
        hint = array.getString(R.styleable.MaterialSearchBar_hint);
        maxSuggestionCount = array.getInt(R.styleable.MaterialSearchBar_maxSuggestionsCount, 3);
        speechMode = array.getBoolean(R.styleable.MaterialSearchBar_speechMode, false);

        hintColor = array.getColor(R.styleable.MaterialSearchBar_hintColor, -1);
        textColor = array.getColor(R.styleable.MaterialSearchBar_textColor, -1);
        navButtonEnabled = array.getBoolean(R.styleable.MaterialSearchBar_navIconEnabled, false);

        destiny = getResources().getDisplayMetrics().density;
        adapter = new SuggestionsAdapter(LayoutInflater.from(getContext()));
        adapter.setListener(this);
        adapter.maxSuggestionsCount = maxSuggestionCount;
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.mt_recycler);
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));

        array.recycle();

        searchIcon = (ImageView) findViewById(R.id.mt_search);
        arrowIcon = (ImageView) findViewById(R.id.mt_arrow);
        searchEdit = (AppCompatEditText) findViewById(R.id.mt_editText);
        inputContainer = (LinearLayout) findViewById(R.id.inputContainer);
        navIcon = (ImageView) findViewById(R.id.mt_nav);
        findViewById(R.id.mt_clear).setOnClickListener(this);

        setOnClickListener(this);
        arrowIcon.setOnClickListener(this);
        searchIcon.setOnClickListener(this);
        searchEdit.setOnFocusChangeListener(this);
        searchEdit.setOnEditorActionListener(this);
        navIcon.setOnClickListener(this);
        postSetup();
    }

    /**
     * Inflate menu for searchBar
     *
     * @param menuResource - menu resource
     */
    public void inflateMenu(int menuResource) {
        this.menuResource = menuResource;
        if (menuResource > 0) {
            ImageView menuIcon = (ImageView) findViewById(R.id.mt_menu);
            RelativeLayout.LayoutParams params = (LayoutParams) searchIcon.getLayoutParams();
            params.rightMargin = (int) (36 * destiny);
            searchIcon.setLayoutParams(params);
            menuIcon.setVisibility(GONE);
            menuIcon.setOnClickListener(this);
            popupMenu = new PopupMenu(getContext(), menuIcon);
            popupMenu.inflate(menuResource);
            popupMenu.setGravity(Gravity.RIGHT);
        }
    }

    /**
     * Get popup menu
     *
     * @return PopupMenu
     */
    public PopupMenu getMenu() {
        return this.popupMenu;
    }

    private void postSetup() {
        if (searchIconRes < 0)
            searchIconRes = R.drawable.ic_magnify_black_48dp;
        setSpeechMode(speechMode);
        if (navIconResId < 0)
            navIconResId = R.drawable.ic_menu_black_24dp;
        setNavigationIcon(navIconResId);
        if (hint != null)
            searchEdit.setHint(hint);
        setupTextColors();
        setNavButtonEnabled(navButtonEnabled);
        if (popupMenu == null)
            findViewById(R.id.mt_menu).setVisibility(GONE);
    }

    private void setupTextColors() {
        if (hintColor != -1)
            searchEdit.setHintTextColor(ContextCompat.getColor(getContext(), hintColor));
        if (textColor != -1)
            searchEdit.setTextColor(ContextCompat.getColor(getContext(), textColor));
    }

    /**
     * Register listener for search bar callbacks.
     *
     * @param onSearchActionListener the callback listener
     */
    public void setOnSearchActionListener(OnSearchActionListener onSearchActionListener) {
        this.onSearchActionListener = onSearchActionListener;
    }

    /**
     * Hides search input and close arrow
     */
    public void disableSearch() {
        searchEnabled = false;
        Animation out = AnimationUtils.loadAnimation(getContext(), R.anim.fade_out);
        Animation in = AnimationUtils.loadAnimation(getContext(), R.anim.fade_in_right);
        out.setAnimationListener(this);
        searchIcon.setVisibility(VISIBLE);
        inputContainer.startAnimation(out);
        //inputContainer.animate().alpha(0).start();
        searchIcon.startAnimation(in);

        if (listenerExists())
            onSearchActionListener.onSearchStateChanged(false);
        if (suggestionsVisible) animateLastRequests(getListHeight(false), 0);
    }

    /**
     * Shows search input and close arrow
     */
    public void enableSearch() {
        adapter.notifyDataSetChanged();
        searchEnabled = true;
        Animation left_in = AnimationUtils.loadAnimation(getContext(), R.anim.fade_in_left);
        Animation left_out = AnimationUtils.loadAnimation(getContext(), R.anim.fade_out_left);
        left_in.setAnimationListener(this);
        inputContainer.setVisibility(VISIBLE);
        inputContainer.startAnimation(left_in);
        //inputContainer.animate().alpha(1).x(0).start();
        if (listenerExists()) {
            onSearchActionListener.onSearchStateChanged(true);
        }
        searchIcon.startAnimation(left_out);
    }

    private void animateLastRequests(int from, int to) {
        suggestionsVisible = to > 0;
        final RelativeLayout last = (RelativeLayout) findViewById(R.id.last);
        final ViewGroup.LayoutParams lp = last.getLayoutParams();
        if (to == 0 && lp.height == 0)
            return;
        ValueAnimator animator = ValueAnimator.ofInt(from, to);
        animator.setDuration(200);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                lp.height = (int) animation.getAnimatedValue();
                last.setLayoutParams(lp);
            }
        });
        if (adapter.getItemCount() > 0)
            animator.start();
    }

    /**
     * Set search icon drawable resource
     *
     * @param searchIconResId icon resource id
     */
    public void setSearchIcon(int searchIconResId) {
        this.searchIconRes = searchIconResId;
        this.searchIcon.setImageResource(searchIconResId);
    }

    /**
     * Set navigation icon drawable resource
     *
     * @param navigationIconResId icon resource id
     */
    public void setNavigationIcon(int navigationIconResId) {
        this.navIconResId = navigationIconResId;
        this.navIcon.setImageResource(navigationIconResId);
    }

    /**
     * Sets search bar hint
     *
     * @param hint
     */
    public void setHint(CharSequence hint) {
        this.hint = hint;
        searchEdit.setHint(hint);
    }

    /**
     * sets the speechMode for the search bar.
     * If set to true, microphone icon will display instead of the search icon.
     * Also clicking on this icon will trigger the callback method onButtonClicked()
     *
     * @param speechMode
     * @see #BUTTON_SPEECH
     * @see OnSearchActionListener#onButtonClicked(int)
     */
    public void setSpeechMode(boolean speechMode) {
        this.speechMode = speechMode;
        if (speechMode) {
            searchIcon.setImageResource(R.drawable.mn_v_sv_mic4);
            searchIcon.setColorFilter(ContextCompat.getColor(getContext(), R.color.colorAccent));
            searchIcon.setClickable(true);
        } else {
            searchIcon.setImageResource(searchIconRes);
            searchIcon.setClickable(false);
        }
    }

    /**
     * True if MaterialSearchBar is in speech mode
     *
     * @return speech mode
     */
    public boolean isSpeechModeEnabled() {
        return speechMode;
    }

    /**
     * Check if search bar is in edit mode
     *
     * @return true if search bar is in edit mode
     */
    public boolean isSearchEnabled() {
        return searchEnabled;
    }

    /**
     * Specifies the maximum number of search queries stored until the activity is destroyed
     *
     * @param maxQuery maximum queries
     */
    public void setMaxSuggestionCount(int maxQuery) {
        this.maxSuggestionCount = maxQuery;
        adapter.maxSuggestionsCount = maxQuery;
    }

    /**
     * Returns the last search queries.
     * The queries are stored only for the duration of one activity session.
     * When the activity is destroyed, the queries will be deleted.
     * To save queries, use the method getLastSuggestions().
     * To recover the queries use the method setLastSuggestions().
     *
     * @return array with the latest search queries
     * @see #setLastSuggestions(List)
     * @see #setMaxSuggestionCount(int)
     */
    public List<String> getLastSuggestions() {
        return adapter.getSuggestions();
    }

    /**
     * Sets the array of recent search queries.
     * It is advisable to save the queries when the activity is destroyed
     * and call this method when creating the activity.
     *
     * @param suggestions an array of queries
     * @see #getLastSuggestions()
     * @see #setMaxSuggestionCount(int)
     */
    public void setLastSuggestions(List<String> suggestions) {
        adapter.setSuggestions(suggestions);
    }

    /**
     * Set search input text color
     *
     * @param textColor text color
     */
    public void setTextColor(int textColor) {
        this.textColor = textColor;
        setupTextColors();
    }

    /**
     * Set text input hint color
     *
     * @param hintColor text hint color
     */
    public void setTextHintColor(int hintColor) {
        this.hintColor = hintColor;
        setupTextColors();
    }

    /**
     * Set navigation drawer menu icon enabled
     *
     * @param navButtonEnabled icon enabled
     */
    public void setNavButtonEnabled(boolean navButtonEnabled) {
        this.navButtonEnabled = navButtonEnabled;
        if (navButtonEnabled) {
            navIcon.setVisibility(VISIBLE);
            navIcon.setClickable(true);
            LayoutParams lp = (LayoutParams) inputContainer.getLayoutParams();
            lp.leftMargin = (int) (50 * destiny);
            inputContainer.setLayoutParams(lp);
            arrowIcon.setVisibility(GONE);
        } else {
            navIcon.setVisibility(GONE);
            navIcon.setClickable(false);
        }
    }


    public void setText(String text) {
        searchEdit.setText(text);
    }

    public String getText() {
        return searchEdit.getText().toString();
    }

    /**
     * Set CardView elevation
     *
     * @param elevation
     */
    public void setCardViewElevation(int elevation) {
        CardView cardView = (CardView) findViewById(R.id.mt_container);
        cardView.setCardElevation(elevation);
    }

    /**
     * Add text watcher to searchbar's EditText
     *
     * @param textWatcher
     */
    public void addTextChangeListener(TextWatcher textWatcher) {
        searchEdit.addTextChangedListener(textWatcher);
    }

    private boolean listenerExists() {
        return onSearchActionListener != null;
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == getId()) {
            if (!searchEnabled) {
                enableSearch();
            }
        } else if (id == R.id.mt_arrow) {
            disableSearch();
        } else if (id == R.id.mt_search) {
            if (listenerExists())
                onSearchActionListener.onButtonClicked(BUTTON_SPEECH);
        } else if (id == R.id.mt_clear) {
            searchEdit.setText("");
            disableSearch();
        } else if (id == R.id.mt_menu) {
            popupMenu.show();
        } else if (id == R.id.mt_nav)
            if (listenerExists())
                onSearchActionListener.onButtonClicked(BUTTON_NAVIGATION);
    }

    @Override
    public void onAnimationStart(Animation animation) {

    }

    @Override
    public void onAnimationEnd(Animation animation) {
        if (!searchEnabled) {
            inputContainer.setVisibility(GONE);
            searchEdit.setText("");
        } else {
            searchIcon.setVisibility(GONE);
            searchEdit.requestFocus();
            animateLastRequests(0, getListHeight(false));
        }
    }

    @Override
    public void onAnimationRepeat(Animation animation) {

    }

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
        if (hasFocus) {
            imm.showSoftInput(v, InputMethodManager.SHOW_IMPLICIT);
        } else {
            imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
        }
    }

    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        if (listenerExists())
            onSearchActionListener.onSearchConfirmed(searchEdit.getText());
        if (suggestionsVisible)
            animateLastRequests(getListHeight(false), 0);
        adapter.addSuggestion(searchEdit.getText().toString());
        return true;
    }

    private int getListHeight(boolean isSubtraction) {
        if (!isSubtraction)
            return (int) ((adapter.getItemCount() * 50) * destiny);
        return (int) (((adapter.getItemCount() - 1) * 50) * destiny);
    }

    @Override
    public void OnItemClickListener(int position, View v) {
        if (v.getTag() instanceof String) {
            searchEdit.setText((String) v.getTag());
        }
    }

    @Override
    public void OnItemDeleteListener(int position, View v) {
        if (v.getTag() instanceof String) {
            /*Order of two line should't be change,
            because sholud calculate the height of item first*/
            animateLastRequests(getListHeight(false), getListHeight(true));
            adapter.deleteSuggestion(position, (String) v.getTag());
        }
    }


        void onButtonClicked(int buttonCode);
    }

    @Override
    protected Parcelable onSaveInstanceState() {
        SavedState savedState = new SavedState(super.onSaveInstanceState());
        savedState.isSearchBarVisible = searchEnabled ? VIEW_VISIBLE : VIEW_INVISIBLE;
        savedState.suggestionsVisible = suggestionsVisible ? VIEW_VISIBLE : VIEW_INVISIBLE;
        savedState.speechMode = speechMode ? VIEW_VISIBLE : VIEW_INVISIBLE;
        savedState.navIconResId = navIconResId;
        savedState.searchIconRes = searchIconRes;
        savedState.suggestions = getLastSuggestions();
        savedState.maxSuggestions = maxSuggestionCount;
        if (hint != null) savedState.hint = hint.toString();
        return savedState;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        SavedState savedState = (SavedState) state;
        super.onRestoreInstanceState(savedState.getSuperState());
        searchEnabled = savedState.isSearchBarVisible == VIEW_VISIBLE;
        suggestionsVisible = savedState.suggestionsVisible == VIEW_VISIBLE;
        setLastSuggestions(savedState.suggestions);
        if (suggestionsVisible)
            animateLastRequests(0, getListHeight(false));
        if (searchEnabled) {
            inputContainer.setVisibility(VISIBLE);
            searchIcon.setVisibility(GONE);
        }
    }

    private static class SavedState extends BaseSavedState {
        private int isSearchBarVisible;
        private int suggestionsVisible;
        private int speechMode;
        private int searchIconRes;
        private int navIconResId;
        private String hint;
        private List<String> suggestions;
        private int maxSuggestions;

        @Override
        public void writeToParcel(Parcel out, int flags) {
            super.writeToParcel(out, flags);
            out.writeInt(isSearchBarVisible);
            out.writeInt(suggestionsVisible);
            out.writeInt(speechMode);

            out.writeInt(searchIconRes);
            out.writeInt(navIconResId);
            out.writeString(hint);
            out.writeList(suggestions);
            out.writeInt(maxSuggestions);
        }

        public SavedState(Parcel source) {
            super(source);
            isSearchBarVisible = source.readInt();
            suggestionsVisible = source.readInt();
            speechMode = source.readInt();

            navIconResId = source.readInt();
            searchIconRes = source.readInt();
            hint = source.readString();
            suggestions = source.readArrayList(null);
            maxSuggestions = source.readInt();
        }

        public SavedState(Parcelable superState) {
            super(superState);
        }

        public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
            @Override
            public SavedState createFromParcel(Parcel source) {
                return new SavedState(source);
            }

            @Override
            public SavedState[] newArray(int size) {
                return new SavedState[size];
            }
        };
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && searchEnabled) {
            animateLastRequests(getListHeight(false), 0);
            disableSearch();
            return true;
        }
        return super.dispatchKeyEvent(event);
    }
}

searchBar xml代码:

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <android.support.v7.widget.CardView
        android:id="@+id/mt_container"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_margin="8dp"
        app:cardBackgroundColor="@android:color/white"
        app:cardElevation="4dp">

        <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/root"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <android.support.v7.widget.AppCompatImageView
                android:id="@+id/mt_menu"
                android:layout_width="36dp"
                android:layout_height="50dp"
                android:layout_alignParentEnd="true"
                android:layout_alignParentRight="true"
                android:layout_alignParentTop="true"
                android:background="?attr/selectableItemBackgroundBorderless"
                android:clickable="true"
                android:padding="13dp"
                android:scaleType="centerCrop"
                android:src="@drawable/ic_dots_vertical_black_48dp"
                android:tint="@color/material_grey_600"
                android:visibility="gone" />

            <android.support.v7.widget.AppCompatImageView
                android:id="@+id/mt_nav"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:layout_alignParentEnd="true"
                android:layout_alignParentRight="true"
                android:layout_weight="1"
                android:clickable="true"
                android:scaleType="center"
                android:tint="@color/colorAccent"
                app:srcCompat="@drawable/ic_menu_black_24dp" />

            <LinearLayout
                android:id="@+id/inputContainer"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:layout_toLeftOf="@+id/mt_menu"
                android:layout_toRightOf="@+id/mt_nav"
                android:layout_toStartOf="@+id/mt_menu"
                android:gravity="center_vertical"
                android:orientation="horizontal"
                android:visibility="gone">

                <android.support.v7.widget.AppCompatImageView
                    android:id="@+id/mt_arrow"
                    android:layout_width="50dp"
                    android:layout_height="50dp"
                    android:background="?attr/selectableItemBackground"
                    android:clickable="true"
                    android:padding="13dp"
                    android:src="@drawable/ic_arrow_left_black_48dp"
                    android:tint="@color/material_grey_600"
                    android:visibility="visible" />

                <android.support.v7.widget.AppCompatEditText
                    android:id="@+id/mt_editText"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_marginLeft="8dp"
                    android:layout_marginRight="8dp"
                    android:layout_weight="1"
                    android:background="@android:color/transparent"
                    android:hint="@string/action_search"
                    android:imeOptions="flagNoExtractUi|actionSearch"
                    android:gravity="right|center_vertical"
                    android:textColor="@color/colorAccent"
                    android:singleLine="true"
                    android:textAppearance="?android:attr/textAppearanceMedium"
                    android:visibility="visible" />

                <android.support.v7.widget.AppCompatImageView
                    android:id="@+id/mt_clear"
                    android:layout_width="50dp"
                    android:layout_height="50dp"
                    android:layout_marginRight="50dp"
                    android:background="?attr/selectableItemBackground"
                    android:padding="14dp"
                    android:src="@drawable/ic_close_black_48dp"
                    android:tint="@color/colorAccent" />

            </LinearLayout>

            <RelativeLayout
                android:id="@+id/last"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_marginTop="50dp">

                <View
                    android:layout_width="match_parent"
                    android:layout_height="1dp"
                    android:background="@color/material_grey_300" />

                <android.support.v7.widget.RecyclerView
                    android:id="@+id/mt_recycler"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />
            </RelativeLayout>

            <android.support.v7.widget.AppCompatImageView
                android:id="@+id/mt_search"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_alignParentTop="true"
                android:clickable="false"
                android:padding="13dp"
                android:src="@drawable/ic_magnify_black_48dp"
                android:tint="@color/colorAccent"
                android:visibility="visible" />

        </RelativeLayout>

    </android.support.v7.widget.CardView>

</merge>

样式代码:

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Light" />

    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />

</resources>

如何修复bug并在sdk 16和17中成功运行?

请帮帮我,谢谢大家&lt; 3

0 个答案:

没有答案