Last active
May 22, 2020 22:48
-
-
Save jaredrummler/c408c9d897fd92d5d116 to your computer and use it in GitHub Desktop.
Revisions
-
Jared Rummler revised this gist
Feb 11, 2015 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -41,7 +41,7 @@ * * <pre> * <code> * SearchViewStyle.on(searchView) * .setCursorColor(Color.WHITE) * .setTextColor(Color.WHITE) * .setHintTextColor(Color.WHITE) -
Jared Rummler revised this gist
Feb 11, 2015 . 1 changed file with 5 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -166,14 +166,14 @@ public SearchView getSearchView() { // TODO: add javadoc private int getId(final String name) { return mSearchView.getContext().getResources() .getIdentifier("android:id/" + name, null, null); } @SuppressWarnings("unchecked") public <T extends View> T getView(final String name) { final int id = getId(name); if (id == 0) { return null; } @@ -344,7 +344,8 @@ public SearchViewStyle setVoiceBtnImageResource(final int resId) { public SearchViewStyle setCommitIcon(final int drawableId) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { try { final Field commitIcon = mSearchView.getClass().getField( "mSuggestionCommitIconResId"); commitIcon.setAccessible(true); commitIcon.set(mSearchView, drawableId); } catch (final Exception ignored) { -
Jared Rummler revised this gist
Feb 11, 2015 . 2 changed files with 356 additions and 353 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,353 +0,0 @@ This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,356 @@ /* * Copyright (C) 2015 Jared Rummler <jared.rummler@gmail.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.jrummyapps.android.ui.searchview; import java.lang.reflect.Field; import java.lang.reflect.Method; import android.annotation.SuppressLint; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.os.Build; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.style.ImageSpan; import android.util.SparseArray; import android.view.Menu; import android.view.View; import android.widget.AutoCompleteTextView; import android.widget.ImageView; import android.widget.SearchView; import android.widget.TextView; /** * * Helper class to style a {@link SearchView}.</p> * * Example usage:</p> * * <pre> * <code> * CustomizeSearchView.on(searchView) * .setCursorColor(Color.WHITE) * .setTextColor(Color.WHITE) * .setHintTextColor(Color.WHITE) * .setSearchHintDrawable(R.drawable.ic_search_api_material) * .setSearchButtonImageResource(R.drawable.ic_search_api_material) * .setCloseBtnImageResource(R.drawable.ic_clear_material) * .setVoiceBtnImageResource(R.drawable.ic_voice_search_api_material) * .setGoBtnImageResource(R.drawable.ic_go_search_api_material) * .setCommitIcon(R.drawable.ic_commit_search_api_material) * .setSubmitAreaDrawableId(R.drawable.abc_textfield_search_activated_mtrl_alpha) * .setSearchPlateDrawableId(R.drawable.abc_textfield_search_activated_mtrl_alpha) * .setSearchPlateTint(Color.WHITE) * .setSubmitAreaTint(Color.WHITE); * </pre> * * </code> * * @author Jared Rummler <jared.rummler@gmail.com> * @since Oct 24, 2014 */ public class SearchViewStyle { // =========================================================== // STATIC FIELDS // =========================================================== // The root view // LinearLayout public static final String SEARCH_BAR = "search_bar"; // This is actually used for the badge icon *or* the badge label (or neither) // TextView public static final String SEARCH_BADGE = "search_badge"; // ImageView public static final String SEARCH_BUTTON = "search_button"; // LinearLayout public static final String SEARCH_EDIT_FRAME = "search_edit_frame"; // ImageView public static final String SEARCH_MAG_ICON = "search_mag_icon"; // LinearLayout public static final String SEARCH_PLATE = "search_plate"; // android.widget.SearchView$SearchAutoComplete which extends AutoCompleteTextView public static final String SEARCH_SRC_TEXT = "search_src_text"; // ImageView public static final String SEARCH_CLOSE_BTN = "search_close_btn"; // LinearLayout public static final String SUBMIT_AREA = "submit_area"; // ImageView public static final String SEARCH_GO_BTN = "search_go_btn"; // ImageView public static final String SEARCH_VOICE_BTN = "search_voice_btn"; // =========================================================== // STATIC METHODS // =========================================================== public static SearchViewStyle on(final Menu menu, final int id) { return new SearchViewStyle(menu, id); } public static SearchViewStyle on(final SearchView searchView) { return new SearchViewStyle(searchView); } @SuppressLint("NewApi") private static void setTint(final Drawable drawable, final int color) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { drawable.setTint(color); } else { drawable.setColorFilter(color, android.graphics.PorterDuff.Mode.SRC_ATOP); } } // =========================================================== // FIELDS // =========================================================== private final SparseArray<View> mViews; private final SearchView mSearchView; // =========================================================== // INITIALIZERS // =========================================================== { mViews = new SparseArray<View>(); } // =========================================================== // CONSTRUCTORS // =========================================================== private SearchViewStyle(final Menu menu, final int id) { this((SearchView) menu.findItem(id).getActionView()); } private SearchViewStyle(final SearchView searchView) { mSearchView = searchView; } // =========================================================== // GETTERS AND SETTERS // =========================================================== public SearchView getSearchView() { return mSearchView; } // =========================================================== // METHODS // =========================================================== // TODO: add javadoc private int getId(String name) { return mSearchView.getContext().getResources() .getIdentifier("android:id/" + name, null, null); } @SuppressWarnings("unchecked") public <T extends View> T getView(String name) { int id = getId(name); if (id == 0) { return null; } View view = mViews.get(id); if (view == null) { view = mSearchView.findViewById(id); } return (T) view; } public SearchViewStyle setSearchPlateDrawableId(final int id) { final View view = getView(SEARCH_PLATE); if (view != null) { view.setBackgroundResource(id); } return this; } public SearchViewStyle setSubmitAreaDrawableId(final int id) { final View view = getView(SUBMIT_AREA); if (view != null) { view.setBackgroundResource(id); } return this; } public SearchViewStyle setSearchPlateTint(final int color) { final View view = getView(SEARCH_PLATE); if (view != null) { final Drawable background = view.getBackground(); if (background != null) { setTint(background, color); } } return this; } public SearchViewStyle setSubmitAreaTint(final int color) { final View view = getView(SUBMIT_AREA); if (view != null) { final Drawable background = view.getBackground(); if (background != null) { setTint(background, color); } } return this; } public SearchViewStyle setGoBtnImageResource(final int resId) { final ImageView imageView = getView(SEARCH_GO_BTN); if (imageView != null) { imageView.setImageResource(resId); } return this; } public SearchViewStyle setSearchButtonImageResource(final int resId) { final ImageView imageView = getView(SEARCH_BUTTON); if (imageView != null) { imageView.setImageResource(resId); } return this; } public SearchViewStyle setTextColor(final int color) { final AutoCompleteTextView editText = getView(SEARCH_SRC_TEXT); if (editText != null) { editText.setTextColor(color); } return this; } public SearchViewStyle setHintTextColor(final int color) { final AutoCompleteTextView editText = getView(SEARCH_SRC_TEXT); if (editText != null) { editText.setHintTextColor(color); } return this; } public SearchViewStyle setSearchHintDrawable(final int id, final String... hint) { return setSearchHintDrawable(mSearchView.getContext().getResources().getDrawable(id), hint); } public SearchViewStyle setSearchHintDrawable(final Drawable drawable, final String... hint) { try { // android.widget.SearchView$SearchAutoComplete extends AutoCompleteTextView final AutoCompleteTextView editText = getView(SEARCH_SRC_TEXT); if (editText == null) { return this; } // http://nlopez.io/how-to-style-the-actionbar-searchview-programmatically/ final Class<?> clazz = Class.forName("android.widget.SearchView$SearchAutoComplete"); // Add the icon as an ImageSpan final Method textSizeMethod = clazz.getMethod("getTextSize"); final Float rawTextSize = (Float) textSizeMethod.invoke(editText); final int textSize = (int) (rawTextSize * 1.25); drawable.setBounds(0, 0, textSize, textSize); // Create hint text final SpannableStringBuilder stopHint = new SpannableStringBuilder(" "); if (hint != null && hint.length == 1) { stopHint.append(hint[0]); } stopHint.setSpan(new ImageSpan(drawable), 1, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); // Set the new hint text final Method setHintMethod = clazz.getMethod("setHint", CharSequence.class); setHintMethod.invoke(editText, stopHint); } catch (final Exception ignored) { } return this; } public SearchViewStyle setCursorResId(final int drawableId) { final AutoCompleteTextView editText = getView(SEARCH_SRC_TEXT); if (editText != null) { try { final Field f = TextView.class.getDeclaredField("mCursorDrawableRes"); f.setAccessible(true); f.set(editText, drawableId); } catch (final Throwable ignored) { } } return this; } public SearchViewStyle setCursorColor(final int color) { final AutoCompleteTextView editText = getView(SEARCH_SRC_TEXT); if (editText != null) { try { final Field fCursorDrawableRes = TextView.class .getDeclaredField("mCursorDrawableRes"); fCursorDrawableRes.setAccessible(true); final int mCursorDrawableRes = fCursorDrawableRes.getInt(editText); final Field fEditor = TextView.class.getDeclaredField("mEditor"); fEditor.setAccessible(true); final Object editor = fEditor.get(editText); final Class<?> clazz = editor.getClass(); final Field fCursorDrawable = clazz.getDeclaredField("mCursorDrawable"); fCursorDrawable.setAccessible(true); final Drawable[] drawables = new Drawable[2]; drawables[0] = editText.getContext().getResources().getDrawable(mCursorDrawableRes); drawables[1] = editText.getContext().getResources().getDrawable(mCursorDrawableRes); drawables[0].setColorFilter(color, PorterDuff.Mode.SRC_IN); drawables[1].setColorFilter(color, PorterDuff.Mode.SRC_IN); fCursorDrawable.set(editor, drawables); } catch (final Throwable ignored) { } } return this; } public SearchViewStyle setCloseBtnImageResource(final int resId) { final ImageView imageView = getView(SEARCH_CLOSE_BTN); if (imageView != null) { imageView.setImageResource(resId); } return this; } public SearchViewStyle setVoiceBtnImageResource(final int resId) { final ImageView imageView = getView(SEARCH_VOICE_BTN); if (imageView != null) { imageView.setImageResource(resId); } return this; } public SearchViewStyle setCommitIcon(final int drawableId) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { try { Field commitIcon = mSearchView.getClass().getField("mSuggestionCommitIconResId"); commitIcon.setAccessible(true); commitIcon.set(mSearchView, drawableId); } catch (final Exception ignored) { } } return this; } } -
Jared Rummler created this gist
Oct 24, 2014 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,353 @@ /* * Copyright (C) 2014 Jared Rummler <jared@jrummyapps.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.jrummyapps.ui; import java.lang.reflect.Field; import java.lang.reflect.Method; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Build; import android.text.InputType; import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.style.ImageSpan; import android.view.Menu; import android.view.View; import android.widget.AutoCompleteTextView; import android.widget.ImageView; import android.widget.SearchView; import android.widget.TextView; /** * Customize {@link android.widget.SearchView}</p> * * This should be used in {@link android.app.Activity#onCreateOptionsMenu(Menu)} after inflating the * menu which has the action view class set as android.widget.SearchView</p> * * Some example usage:</p> * * <pre> * <code> * new SearchViewCustomizer(menu, R.id.menu_search).setBackgroundColor(Color.TRANSPARENT) * .setEditTextColor(ColorUtils.WHITE).setEditTextHintColor(Color.LTGRAY) * .setEditTextInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) * .setEditTextTypeface(robotoLight).setSearchHintDrawable(searchIcon, "filename") * .setEditTextCursorResId(R.drawable.white_cursor) * .setCloseDrawable(closeDrawable) * .setEditTextBackground(R.drawable.material_edit_text); * </code> * </pre> * * @author Jared Rummler <jared@jaredrummler.com> * @version 1.0 * @since Oct 24, 2014 */ public class SearchViewCustomizer { // =========================================================== // Constants // =========================================================== // =========================================================== // Static Fields // =========================================================== // =========================================================== // Static Initializers // =========================================================== // =========================================================== // Static Methods // =========================================================== // =========================================================== // Fields // =========================================================== private final SearchView mSearchView; private final int mSearchPlateId; private final int mSearchSrcTextId; private final int mSearchCloseBtnId; // =========================================================== // Initializers // =========================================================== // =========================================================== // Constructors // =========================================================== public SearchViewCustomizer(Menu menu, int id) { this((SearchView) menu.findItem(id).getActionView()); } public SearchViewCustomizer(SearchView searchView) { mSearchView = searchView; mSearchSrcTextId = searchView.getContext().getResources() .getIdentifier("android:id/search_src_text", null, null); mSearchPlateId = searchView.getContext().getResources() .getIdentifier("android:id/search_plate", null, null); mSearchCloseBtnId = searchView.getContext().getResources() .getIdentifier("android:id/search_close_btn", null, null); } // =========================================================== // Getter & Setter // =========================================================== // =========================================================== // Methods for/from SuperClass/Interfaces // =========================================================== // =========================================================== // Methods // =========================================================== /** * Set the background of the search plate. * * @param resid * The identifier of the resource. * @return */ public SearchViewCustomizer setBackgroundResource(int resid) { if (mSearchPlateId != 0) { View searchPlate = findById(mSearchPlateId); searchPlate.setBackgroundResource(resid); } return this; } /** * Set the background of the search plate * * @param color * The color of the background * @return */ public SearchViewCustomizer setBackgroundColor(int color) { if (mSearchPlateId != 0) { View searchPlate = findById(mSearchPlateId); searchPlate.setBackgroundColor(color); } return this; } /** * Set the background of the search plate * * @param background * The Drawable to use as the background, or null to remove the background * @return */ @SuppressWarnings("deprecation") public SearchViewCustomizer setBackgroundDrawable(Drawable background) { if (mSearchPlateId != 0) { View searchPlate = findById(mSearchPlateId); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { searchPlate.setBackground(background); } else { searchPlate.setBackgroundDrawable(background); } } return this; } /** * Set the text color for the EditText * * @param color * @return */ public SearchViewCustomizer setEditTextColor(int color) { if (mSearchSrcTextId != 0) { AutoCompleteTextView searchEditText = findById(mSearchSrcTextId); searchEditText.setTextColor(color); } return this; } /** * Sets the color of the hint text for all the states (disabled, focussed, selected...) * * @param color * @return */ public SearchViewCustomizer setEditTextHintColor(int color) { if (mSearchSrcTextId != 0) { AutoCompleteTextView searchEditText = findById(mSearchSrcTextId); searchEditText.setHintTextColor(color); } return this; } /** * Set the background for the EditText displayed in the SearchView * * @param resId * The identifier of the resource. * @return */ public SearchViewCustomizer setEditTextBackground(int resId) { if (mSearchSrcTextId != 0) { AutoCompleteTextView searchEditText = findById(mSearchSrcTextId); searchEditText.setBackgroundResource(resId); } return this; } /** * Set any input types on the EditText, such as {@link InputType#TYPE_TEXT_FLAG_NO_SUGGESTIONS} * * @param type * @return */ public SearchViewCustomizer setEditTextInputType(int type) { if (mSearchSrcTextId != 0) { AutoCompleteTextView searchEditText = findById(mSearchSrcTextId); searchEditText.setInputType(type); } return this; } /** * Apply a custom typeface to the search field EditText * * @param tf * @return */ public SearchViewCustomizer setEditTextTypeface(Typeface tf) { if (mSearchSrcTextId != 0) { AutoCompleteTextView searchEditText = findById(mSearchSrcTextId); searchEditText.setTypeface(tf); } return this; } /** * Set the search icon that appears before the hint text. * * @param drawable * The drawable to use for the hint. * @param hint * The text for the hint. * @return */ public SearchViewCustomizer setSearchHintDrawable(Drawable drawable, String hint) { if (mSearchSrcTextId != 0) { AutoCompleteTextView searchEditText = findById(mSearchSrcTextId); try { // http://nlopez.io/how-to-style-the-actionbar-searchview-programmatically/ Class<?> clazz = Class.forName("android.widget.SearchView$SearchAutoComplete"); // Add the icon as an spannable Method textSizeMethod = clazz.getMethod("getTextSize"); Float rawTextSize = (Float) textSizeMethod.invoke(searchEditText); int textSize = (int) (rawTextSize * 1.25); drawable.setBounds(0, 0, textSize, textSize); // Create hint text SpannableStringBuilder stopHint = new SpannableStringBuilder(" "); stopHint.append(hint); stopHint.setSpan(new ImageSpan(drawable), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); // Set the new hint text Method setHintMethod = clazz.getMethod("setHint", CharSequence.class); setHintMethod.invoke(searchEditText, stopHint); } catch (Exception ignored) { } } return this; } /** * Set the cursor that will be used in the EditText. * * @param resId * The resource id for your custom cursor. * @return */ public SearchViewCustomizer setEditTextCursorResId(int resId) { if (mSearchSrcTextId != 0) { AutoCompleteTextView searchEditText = findById(mSearchSrcTextId); try { // https://github.com/android/platform_frameworks_base/blob/kitkat-release/core/java/android/widget/TextView.java#L562-564 Field f = TextView.class.getDeclaredField("mCursorDrawableRes"); f.setAccessible(true); f.set(searchEditText, resId); } catch (Exception ignored) { } } return this; } /** * Set the cancel drawable. * * @param drawable * The drawable to set * @return */ public SearchViewCustomizer setCloseDrawable(Drawable drawable) { if (mSearchCloseBtnId != 0) { ImageView searchCloseBtn = findById(mSearchCloseBtnId); searchCloseBtn.setImageDrawable(drawable); } return this; } /** * * @return The {@link AutoCompleteTextView} that is used in the {@link SearchView} or * {@code null} if we failed to find it. */ public AutoCompleteTextView getAutoCompleteTextView() { if (mSearchSrcTextId == 0) return null; return findById(mSearchSrcTextId); } /** * * @return The {@link ImageView} that is used as the close button in the {@link SearchView} or * {@code null} if we failed to find it. */ public ImageView getCloseButton() { if (mSearchCloseBtnId == 0) return null; return findById(mSearchCloseBtnId); } /** * * @return The search plate that holds most of the views in the {@link SearchView} or * {@code null} if we failed to find it. */ public View getSearchPlate() { if (mSearchPlateId == 0) return null; return findById(mSearchPlateId); } @SuppressWarnings("unchecked") private <T extends View> T findById(int id) { return (T) mSearchView.findViewById(id); } // =========================================================== // Inner and Anonymous Classes and/or Interfaces // =========================================================== }