머티리얼 디자인 가이드 라인처럼 보이는 SearchView 생성


134

현재 앱을 머티리얼 디자인으로 변환하는 방법을 배우는 중입니다. 지금 조금 멈췄습니다. 툴바가 추가되었고 내 탐색 서랍이 모든 콘텐츠를 오버레이하도록 만들었습니다.

이제 재료 가이드 라인 과 비슷한 확장 가능한 검색을 작성하려고합니다 . 여기에 이미지 설명을 입력하십시오

이것이 바로 지금 얻은 것이며 위와 같이 만드는 방법을 알 수 없습니다.
내 검색

이것은 내 메뉴 XML입니다.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_search"
        android:icon="@android:drawable/ic_menu_search"
        android:title="Search"
        app:showAsAction="always"
        app:actionViewClass="android.support.v7.widget.SearchView" />
</menu>

작동하지만 SearchView로 확장되는 메뉴 항목이 표시되며 내 목록을 잘 필터링 할 수 있습니다. 그래도 첫 번째 그림처럼 보이지 않습니다.

내가 사용하려고 MenuItemCompat.setOnActionExpandListener()R.id.action_search나는 뒤로 화살표에 홈 아이콘을 변경할 수 있도록,하지만 작동하지 않습니다. 리스너에서 아무것도 발생하지 않습니다. 그것이 효과가 있었지만 여전히 첫 번째 이미지에 그리 가깝지는 않습니다.

재료 가이드 라인처럼 보이는 새로운 appcompat 도구 모음에서 SearchView를 작성하는 방법


6
app : showAsAction = "always | collapseActionView"
Pavlos

당신은 여기 내 대답을 살펴 할 수 있습니다 : stackoverflow.com/a/41013994/5326551
shnizlon

답변:


152

android.support.v7라이브러리를 사용하는 경우 실제로이 작업을 수행하는 것이 매우 쉽습니다 .

1 단계

메뉴 항목 선언

<item android:id="@+id/action_search"
    android:title="Search"
    android:icon="@drawable/abc_ic_search_api_mtrl_alpha"
    app:showAsAction="ifRoom|collapseActionView"
    app:actionViewClass="android.support.v7.widget.SearchView" />

2 단계

SearchView를 확장 AppCompatActivity하고 onCreateOptionsMenu설정하십시오.

import android.support.v7.widget.SearchView;

...

public class YourActivity extends AppCompatActivity {

    ...

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_home, menu);
        // Retrieve the SearchView and plug it into SearchManager
        final SearchView searchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.action_search));
        SearchManager searchManager = (SearchManager) getSystemService(SEARCH_SERVICE);
        searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        return true;
    }

    ... 

}

결과

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오


2
나는 그것을 upvoted했지만 어떤 에뮬레이터를 사용하고 있습니까? 나는 그것을 시도했지만 navigate-back버튼을 얻지 못하고 오히려 검색 아이콘을 얻었고 화면의 왼쪽 가장자리와의 거리는 X아이콘과 화면의 오른쪽 가장자리 사이의 거리와 동일 하지 않습니다 ( 액션 오버플로). 여기에 질문을 게시 했습니다. 살펴볼 수 있습니까?
Solace

13
재료 검색이 아닙니다. 이 작업 표시 줄 만 보통 오래된 검색입니다
고팔 싱 Sirvi

2
검색 버튼을 클릭 할 필요없이 항상 표시 할 수 있도록 자체 하위 질문에 대답했습니다 . 기능에 줄 searchView.setIconifiedByDefault(false);을 추가하십시오 onCreateOptionsMenu.
adelriosantiago

3
또 다른 유용한 재미있는 이야기 - 당신이 검색보기는 처음 확장하려는 경우가 있는지 확인 app:showAsAction="always"하고 NOTapp:showAsAction="ifRoom|collapseActionView"
인 Vinay W

1
또한이 방법을 사용하면 searchBar가 확장 된 경우에도 OverflowIcon이 계속 표시됩니다 (예 : 3 도트). 그러나 일부 앱은 검색을 완전히 확장하고 배경을 흰색으로 변경하여 검색을 처리합니다. Gmail과 마찬가지로
Zen

83

일주일 동안 수수께끼를 푼 후. 내가 알아 낸 것 같아
툴바 내에서 EditText 만 사용하고 있습니다. 이것은 reddit에서 oj88에 의해 제안되었습니다.

나는 이제 이것을 가지고있다 :
새로운 SearchView

먼저 내 활동의 onCreate () 내부에 오른쪽과 같이 이미지보기가있는 EditText를 툴바에 다음과 같이 추가했다 :

    // Setup search container view
    searchContainer = new LinearLayout(this);
    Toolbar.LayoutParams containerParams = new Toolbar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
    containerParams.gravity = Gravity.CENTER_VERTICAL;
    searchContainer.setLayoutParams(containerParams);

    // Setup search view
    toolbarSearchView = new EditText(this);
    // Set width / height / gravity
    int[] textSizeAttr = new int[]{android.R.attr.actionBarSize};
    int indexOfAttrTextSize = 0;
    TypedArray a = obtainStyledAttributes(new TypedValue().data, textSizeAttr);
    int actionBarHeight = a.getDimensionPixelSize(indexOfAttrTextSize, -1);
    a.recycle();
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, actionBarHeight);
    params.gravity = Gravity.CENTER_VERTICAL;
    params.weight = 1;
    toolbarSearchView.setLayoutParams(params);

    // Setup display
    toolbarSearchView.setBackgroundColor(Color.TRANSPARENT);
    toolbarSearchView.setPadding(2, 0, 0, 0);
    toolbarSearchView.setTextColor(Color.WHITE);
    toolbarSearchView.setGravity(Gravity.CENTER_VERTICAL);
    toolbarSearchView.setSingleLine(true);
    toolbarSearchView.setImeActionLabel("Search", EditorInfo.IME_ACTION_UNSPECIFIED);
    toolbarSearchView.setHint("Search");
    toolbarSearchView.setHintTextColor(Color.parseColor("#b3ffffff"));
    try {
        // Set cursor colour to white
        // https://stackoverflow.com/a/26544231/1692770
        // 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(toolbarSearchView, R.drawable.edittext_whitecursor);
    } catch (Exception ignored) {
    }

    // Search text changed listener
    toolbarSearchView.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            Fragment mainFragment = getFragmentManager().findFragmentById(R.id.container);
            if (mainFragment != null && mainFragment instanceof MainListFragment) {
                ((MainListFragment) mainFragment).search(s.toString());
            }
        }

        @Override
        public void afterTextChanged(Editable s) {
            // https://stackoverflow.com/a/6438918/1692770
            if (s.toString().length() <= 0) {
                toolbarSearchView.setHintTextColor(Color.parseColor("#b3ffffff"));
            }
        }
    });
    ((LinearLayout) searchContainer).addView(toolbarSearchView);

    // Setup the clear button
    searchClearButton = new ImageView(this);
    Resources r = getResources();
    int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16, r.getDisplayMetrics());
    LinearLayout.LayoutParams clearParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    clearParams.gravity = Gravity.CENTER;
    searchClearButton.setLayoutParams(clearParams);
    searchClearButton.setImageResource(R.drawable.ic_close_white_24dp); // TODO: Get this image from here: https://github.com/google/material-design-icons
    searchClearButton.setPadding(px, 0, px, 0);
    searchClearButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            toolbarSearchView.setText("");
        }
    });
    ((LinearLayout) searchContainer).addView(searchClearButton);

    // Add search view to toolbar and hide it
    searchContainer.setVisibility(View.GONE);
    toolbar.addView(searchContainer);

이것은 효과가 있었지만 홈 버튼을 눌렀을 때 onOptionsItemSelected ()가 호출되지 않는 문제가 발생했습니다. 그래서 홈 버튼을 눌러 검색을 취소 할 수 없었습니다. 홈 버튼에 클릭 리스너를 등록하는 몇 가지 방법을 시도했지만 작동하지 않았습니다.

결국 나는 가지고 있던 ActionBarDrawerToggle이 물건을 방해하고 있다는 것을 알았으므로 그것을 제거했습니다. 이 리스너는 다음 작업을 시작했습니다.

    toolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // toolbarHomeButtonAnimating is a boolean that is initialized as false. It's used to stop the user pressing the home button while it is animating and breaking things.
            if (!toolbarHomeButtonAnimating) {
                // Here you'll want to check if you have a search query set, if you don't then hide the search box.
                // My main fragment handles this stuff, so I call its methods.
                FragmentManager fragmentManager = getFragmentManager();
                final Fragment fragment = fragmentManager.findFragmentById(R.id.container);
                if (fragment != null && fragment instanceof MainListFragment) {
                    if (((MainListFragment) fragment).hasSearchQuery() || searchContainer.getVisibility() == View.VISIBLE) {
                        displaySearchView(false);
                        return;
                    }
                }
            }

            if (mDrawerLayout.isDrawerOpen(findViewById(R.id.navigation_drawer)))
                mDrawerLayout.closeDrawer(findViewById(R.id.navigation_drawer));
            else
                mDrawerLayout.openDrawer(findViewById(R.id.navigation_drawer));
        }
    });

이제 홈 버튼으로 검색을 취소 할 수 있지만 뒤로 버튼을 눌러 취소 할 수는 없습니다. 그래서 이것을 onBackPressed ()에 추가했습니다.

    FragmentManager fragmentManager = getFragmentManager();
    final Fragment mainFragment = fragmentManager.findFragmentById(R.id.container);
    if (mainFragment != null && mainFragment instanceof MainListFragment) {
        if (((MainListFragment) mainFragment).hasSearchQuery() || searchContainer.getVisibility() == View.VISIBLE) {
            displaySearchView(false);
            return;
        }
    }

이 메소드를 작성하여 EditText 및 메뉴 항목의 가시성을 토글합니다.

public void displaySearchView(boolean visible) {
    if (visible) {
        // Stops user from being able to open drawer while searching
        mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);

        // Hide search button, display EditText
        menu.findItem(R.id.action_search).setVisible(false);
        searchContainer.setVisibility(View.VISIBLE);

        // Animate the home icon to the back arrow
        toggleActionBarIcon(ActionDrawableState.ARROW, mDrawerToggle, true);

        // Shift focus to the search EditText
        toolbarSearchView.requestFocus();

        // Pop up the soft keyboard
        new Handler().postDelayed(new Runnable() {
            public void run() {
                toolbarSearchView.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 0, 0, 0));
                toolbarSearchView.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, 0, 0, 0));
            }
        }, 200);
    } else {
        // Allows user to open drawer again
        mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);

        // Hide the EditText and put the search button back on the Toolbar.
        // This sometimes fails when it isn't postDelayed(), don't know why.
        toolbarSearchView.postDelayed(new Runnable() {
            @Override
            public void run() {
                toolbarSearchView.setText("");
                searchContainer.setVisibility(View.GONE);
                menu.findItem(R.id.action_search).setVisible(true);
            }
        }, 200);

        // Turn the home button back into a drawer icon
        toggleActionBarIcon(ActionDrawableState.BURGER, mDrawerToggle, true);

        // Hide the keyboard because the search box has been hidden
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(toolbarSearchView.getWindowToken(), 0);
    }
}

툴바의 홈 버튼을 서랍 아이콘과 뒤로 버튼 사이에서 전환하는 방법이 필요했습니다. 결국 이 SO 답변 에서 아래 방법을 찾았습니다 . 좀 더 이해하기 쉽게 약간 수정했지만 :

private enum ActionDrawableState {
    BURGER, ARROW
}

/**
 * Modified version of this, https://stackoverflow.com/a/26836272/1692770<br>
 * I flipped the start offset around for the animations because it seemed like it was the wrong way around to me.<br>
 * I also added a listener to the animation so I can find out when the home button has finished rotating.
 */
private void toggleActionBarIcon(final ActionDrawableState state, final ActionBarDrawerToggle toggle, boolean animate) {
    if (animate) {
        float start = state == ActionDrawableState.BURGER ? 1.0f : 0f;
        float end = Math.abs(start - 1);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            ValueAnimator offsetAnimator = ValueAnimator.ofFloat(start, end);
            offsetAnimator.setDuration(300);
            offsetAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
            offsetAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    float offset = (Float) animation.getAnimatedValue();
                    toggle.onDrawerSlide(null, offset);
                }
            });
            offsetAnimator.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {

                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    toolbarHomeButtonAnimating = false;
                }

                @Override
                public void onAnimationCancel(Animator animation) {

                }

                @Override
                public void onAnimationRepeat(Animator animation) {

                }
            });
            toolbarHomeButtonAnimating = true;
            offsetAnimator.start();
        }
    } else {
        if (state == ActionDrawableState.BURGER) {
            toggle.onDrawerClosed(null);
        } else {
            toggle.onDrawerOpened(null);
        }
    }
}

이것은 효과가 있습니다. 나는 길을 따라 찾은 몇 가지 버그를 해결했습니다. 나는 그것이 100 %라고 생각하지 않지만 그것은 나를 위해 충분히 잘 작동합니다.

편집 : Java 대신 XML로 검색보기를 추가하려면 다음을 수행하십시오.

toolbar.xml :

<android.support.v7.widget.Toolbar 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/toolbar"
    contentInsetLeft="72dp"
    contentInsetStart="72dp"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    android:elevation="4dp"
    android:minHeight="?attr/actionBarSize"
    app:contentInsetLeft="72dp"
    app:contentInsetStart="72dp"
    app:popupTheme="@style/ActionBarPopupThemeOverlay"
    app:theme="@style/ActionBarThemeOverlay">

    <LinearLayout
        android:id="@+id/search_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_vertical"
        android:orientation="horizontal">

        <EditText
            android:id="@+id/search_view"
            android:layout_width="0dp"
            android:layout_height="?attr/actionBarSize"
            android:layout_weight="1"
            android:background="@android:color/transparent"
            android:gravity="center_vertical"
            android:hint="Search"
            android:imeOptions="actionSearch"
            android:inputType="text"
            android:maxLines="1"
            android:paddingLeft="2dp"
            android:singleLine="true"
            android:textColor="#ffffff"
            android:textColorHint="#b3ffffff" />

        <ImageView
            android:id="@+id/search_clear"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:paddingLeft="16dp"
            android:paddingRight="16dp"
            android:src="@drawable/ic_close_white_24dp" />
    </LinearLayout>
</android.support.v7.widget.Toolbar>

활동의 onCreate () :

    searchContainer = findViewById(R.id.search_container);
    toolbarSearchView = (EditText) findViewById(R.id.search_view);
    searchClearButton = (ImageView) findViewById(R.id.search_clear);

    // Setup search container view
    try {
        // Set cursor colour to white
        // https://stackoverflow.com/a/26544231/1692770
        // 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(toolbarSearchView, R.drawable.edittext_whitecursor);
    } catch (Exception ignored) {
    }

    // Search text changed listener
    toolbarSearchView.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            Fragment mainFragment = getFragmentManager().findFragmentById(R.id.container);
            if (mainFragment != null && mainFragment instanceof MainListFragment) {
                ((MainListFragment) mainFragment).search(s.toString());
            }
        }

        @Override
        public void afterTextChanged(Editable s) {
        }
    });

    // Clear search text when clear button is tapped
    searchClearButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            toolbarSearchView.setText("");
        }
    });

    // Hide the search view
    searchContainer.setVisibility(View.GONE);

훌륭하게 작동합니다. 감사합니다! 그러나 코드에서 레이아웃을 만드는 대신 EditText 및 ImageView를 xml로 사용하여 LinearLayout을 만들고 onCreate에서 팽창했습니다.
aluxian 2014

예, XML로 시도했지만 Android Studio가 레이아웃 XML에서 자동 완성 기능을 제공하지 않기 때문에 내가 잘못하고 있다고 생각했습니다.
Mike

이 답변에 필요한 각 XML 레이아웃 디자인으로이 답변을 업데이트 할 수 있습니까? 다른 도움이 될 수 있습니다.
Shreyash Mahajan

1
@Mike 답변을 업데이트하고 완전한 github 소스 코드를 넣을 수 있습니까?
Hamed Ghadirian

1
완성 된 프로젝트를 github
Nilabja


19

질문의 첫 번째 스크린 샷은 공개 위젯이 아닙니다. 지원 SearchView ( android.support.v7.widget.SearchView)는 Android 5.0 Lollipop의 SearchView ( android.widget.SearchView)와 유사 합니다. 두 번째 스크린 샷은 Google Play와 같은 다른 재료로 설계된 앱에서 사용됩니다.

첫 번째 스크린 샷의 SearchView는 드라이브, YouTube 및 기타 비공개 소스 Google Apps에서 사용됩니다. 다행히도 Android 5.0 Dialer 에서도 사용됩니다 . 뷰를 백 포트하려고 할 수 있지만 일부 5.0 API를 사용합니다.

보고 싶은 수업은 다음과 같습니다.

SearchEditTextLayout , AnimUtilsDialtactsActivity 를 사용하여 View 사용 방법을 이해하십시오. ContactsCommon의 리소스도 필요합니다 .

행운을 빕니다.


조사해 주셔서 감사합니다. 이미 할 수있는 일이 있기를 바랐습니다. 지금은 투명한 배경의 EditText를 사용했으며 필요한 것으로 괜찮습니다.
Mike

111
이 대답은 나에게 매우 방해가됩니다. Google은 왜 자체 소재 디자인 가이드 라인과 일치하는 개인 위젯을 사용하고 그렇지 않은 크 래피 위젯을 게시합니까? 그리고 모든 개발자가 이제 스스로 혼자서 고투하고 있습니까? 이것에 대한 가능한 추론은 무엇입니까?
Greg Ennis

18

이 작업을 수행하려는 시도는 다음과 같습니다.

1 단계 : 이름이 지정된 스타일 만들기 SearchViewStyle

<style name="SearchViewStyle" parent="Widget.AppCompat.SearchView">
    <!-- Gets rid of the search icon -->
    <item name="searchIcon">@drawable/search</item>
    <!-- Gets rid of the "underline" in the text -->
    <item name="queryBackground">@null</item>
    <!-- Gets rid of the search icon when the SearchView is expanded -->
    <item name="searchHintIcon">@null</item>
    <!-- The hint text that appears when the user has not typed anything -->
    <item name="queryHint">@string/search_hint</item>
</style>

2 단계 : 이름이 지정된 레이아웃 생성 simple_search_view_item.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.SearchView
    android:layout_gravity="end"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    style="@style/SearchViewStyle"
    xmlns:android="http://schemas.android.com/apk/res/android" />  

3 단계 :이 검색보기에 대한 메뉴 항목 작성

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        app:actionLayout="@layout/simple_search_view_item"
        android:title="@string/search"
        android:icon="@drawable/search"
        app:showAsAction="always" />
</menu>  

4 단계 : 메뉴 팽창

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu_searchable_activity, menu);
    return true;
}  

결과:

여기에 이미지 설명을 입력하십시오

내가 할 수 없었던 유일한 것은의 전체 너비를 채우는 것 Toolbar입니다. 누군가 내가 그렇게 할 수 있다면 그것은 황금색 일 것입니다.


1
I wasn't able to do was to make it fill the entire width, 어떤 지원 라이브러리 버전을 사용하고 있습니까? app:contentInsetStartWithNavigation="0dp"툴바를 설정해보십시오 .
Mangesh

@LittleChild, Magnesh가 제공 한 솔루션을 사용해보십시오. 여전히 문제가 해결되지 않으면 툴바에 아래 줄을 추가하십시오. app : contentInsetStartWithNavigation = "0dp"app : contentInsetLeft = "0dp"app : contentInsetStart = "0dp"app : paddingStart = "0dp"android : layout_marginLeft = "0dp"android : layout_marginStart = "0dp"
Shreyash Mahajan

SearchViewStyle의 각 줄에 대해 설명해 주셔서 감사합니다!
Shinta S

작은 아이는 폭 전체를 들어, 다음과 같은 STH을 수행 할 수 있습니다 ( " stackoverflow.com/questions/27946569/... )
Ali_dev

10

원하는 SearchView 모양을 얻기 위해 스타일을 사용할 수 있습니다.

먼저 styleSearchView 를 작성 해야합니다.

<style name="CustomSearchView" parent="Widget.AppCompat.SearchView">
    <item name="searchIcon">@null</item>
    <item name="queryBackground">@null</item>
</style>

기사의 "SearchView"섹션 에서 찾을 수있는 전체 속성 목록입니다 .

둘째, 당신은을 만들 필요가 style당신을 위해 Toolbar, 액션 바로 사용된다 :

<style name="ToolbarSearchView" parent="Base.ThemeOverlay.AppCompat.Dark.ActionBar">
    <item name="searchViewStyle">@style/CustomSearchView</item>
</style>

마지막으로 툴바 테마 속성을 다음과 같이 업데이트해야합니다.

<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    app:theme="@style/ToolbarSearchView" />

결과:

여기에 이미지 설명을 입력하십시오

참고 : Toolbar테마 속성을 직접 변경해야합니다 . 기본 테마 searchViewStyle속성 만 업데이트하면에 영향을 미치지 않습니다 Toolbar.


navigate-back(뒤로 화살표)와 cancel(x) 아이콘을 직접 추가 했습니까? 아니면 자동으로 추가 되었습니까?
Solace

1
@Solace는 자동으로 추가됩니다
Artem

SearchView에서 검색 쿼리 작성을 시작할 때만 나타나거나 아무 것도 쓰지 않았고 검색 힌트가 보이는 경우에도 나타 납니까? 쿼리 작성을 시작할 때까지 내 것이 나타나지 않기 때문에 묻습니다. 이 정보는 저에게 매우 유용 할 것입니다
Solace

1
@Solace navigate-back는 항상 표시되며 clear일부 검색어를 작성한 후에 만 ​​표시됩니다.
Artem

6

원하는 효과를 얻을 수있는 또 다른 방법은이 재료 검색 뷰 라이브러리를 사용하는 것 입니다. 검색 기록을 자동으로 처리하며보기에 검색 제안을 제공 할 수도 있습니다.

샘플 : (포르투갈어로 표시되지만 영어와 이탈리아어로도 작동합니다).

견본

설정

이 lib를 사용하기 전에 앱 모듈 MsvAuthoritybr.com.mauker패키지 내에 이름이 지정된 클래스를 구현 해야하며라는 공용 정적 문자열 변수가 있어야합니다 CONTENT_AUTHORITY. 원하는 값을 지정하고 매니페스트 파일에 동일한 이름을 추가하는 것을 잊지 마십시오 . lib는이 파일을 사용하여 컨텐츠 제공자 권한을 설정합니다.

예:

MsvAuthority.java

package br.com.mauker;

public class MsvAuthority {
    public static final String CONTENT_AUTHORITY = "br.com.mauker.materialsearchview.searchhistorydatabase";
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest ...>

    <application ... >
        <provider
        android:name="br.com.mauker.materialsearchview.db.HistoryProvider"
        android:authorities="br.com.mauker.materialsearchview.searchhistorydatabase"
        android:exported="false"
        android:protectionLevel="signature"
        android:syncable="true"/>
    </application>

</manifest>

용법

사용하려면 종속성을 추가하십시오.

compile 'br.com.mauker.materialsearchview:materialsearchview:1.2.0'

그런 다음 Activity레이아웃 파일에서 다음을 추가하십시오.

<br.com.mauker.materialsearchview.MaterialSearchView
    android:id="@+id/search_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

그 후, 당신은 단지 얻을해야합니다 MaterialSearchView사용하여 참조를 getViewById()하고, 그것을 열거 나 사용하여 종료 MaterialSearchView#openSearch()하고 MaterialSearchView#closeSearch().

추신 : 에서뿐만 아니라보기를 열고 닫을 수 있습니다 Toolbar. 플로팅 액션 버튼과 같은 openSearch()기본적으로 메소드를 사용할 수 있습니다 Button.

// Inside onCreate()
MaterialSearchView searchView = (MaterialSearchView) findViewById(R.id.search_view);
Button bt = (Button) findViewById(R.id.button);

bt.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            searchView.openSearch();
        }
    });

뒤로 버튼을 사용하여 다음을 수행하여보기를 닫을 수도 있습니다.

@Override
public void onBackPressed() {
    if (searchView.isOpen()) {
        // Close the search on the back button press.
        searchView.closeSearch();
    } else {
        super.onBackPressed();
    }
}

lib 사용 방법에 대한 자세한 내용 은 github 페이지를 확인하십시오 .


2
훌륭한 라이브러리 및 열기 / 닫기 방법을 추상화하여 MenuItem이 그것을 열거 나 닫을 필요가 없도록하는 좋은 아이디어, 검색 아이콘이있는 FloatingActionButton과 함께 내 앱에서 이것을 사용할 계획이므로 훌륭하게 작동합니다.
AdamMc331

'검색'과 같은 문자열에 대한 매개 변수가없는 이유는 무엇입니까? 도서관은 사람들이 영어 또는 포르투갈어 버전의 문자열로 제한하는 것 같습니다 : /
Aspiring Dev

그러나 README에 명시된 스타일을 사용하여 힌트 문자열을 변경할 수 있습니다. 음성 입력 힌트는 나중에 발표 될 예정입니다 : github.com/Mauker1/MaterialSearchView/issues/23
Mauker

@rpgmaker 최신 업데이트를 확인하십시오. 이제 해당 문자열을 변경할 수 있습니다.
Mauker

@Mauker android : imeOptions = "actionSearch"를 구성 요소의 EditText로 설정하는 방법을 알고 있습니까? (키보드에 "검색"버튼을 표시하고 싶습니다)
Greg

2

다음은 Gmail에서와 동일한 SearchView를 만들어 지정된 툴바에 추가합니다. 자신 만의 "ViewUtil.convertDpToPixel"메소드를 구현하면됩니다.

private SearchView createMaterialSearchView(Toolbar toolbar, String hintText) {

    setSupportActionBar(toolbar);
    ActionBar actionBar = getSupportActionBar();
    actionBar.setDisplayHomeAsUpEnabled(true);
    actionBar.setDisplayShowCustomEnabled(true);
    actionBar.setDisplayShowTitleEnabled(false);

    SearchView searchView = new SearchView(this);
    searchView.setIconifiedByDefault(false);
    searchView.setMaxWidth(Integer.MAX_VALUE);
    searchView.setMinimumHeight(Integer.MAX_VALUE);
    searchView.setQueryHint(hintText);

    int rightMarginFrame = 0;
    View frame = searchView.findViewById(getResources().getIdentifier("android:id/search_edit_frame", null, null));
    if (frame != null) {
        LinearLayout.LayoutParams frameParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        rightMarginFrame = ((LinearLayout.LayoutParams) frame.getLayoutParams()).rightMargin;
        frameParams.setMargins(0, 0, 0, 0);
        frame.setLayoutParams(frameParams);
    }

    View plate = searchView.findViewById(getResources().getIdentifier("android:id/search_plate", null, null));
    if (plate != null) {
        plate.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        plate.setPadding(0, 0, rightMarginFrame, 0);
        plate.setBackgroundColor(Color.TRANSPARENT);
    }

    int autoCompleteId = getResources().getIdentifier("android:id/search_src_text", null, null);
    if (searchView.findViewById(autoCompleteId) != null) {
        EditText autoComplete = (EditText) searchView.findViewById(autoCompleteId);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, (int) ViewUtil.convertDpToPixel(36));
        params.weight = 1;
        params.gravity = Gravity.CENTER_VERTICAL;
        params.leftMargin = rightMarginFrame;
        autoComplete.setLayoutParams(params);
        autoComplete.setTextSize(16f);
    }

    int searchMagId = getResources().getIdentifier("android:id/search_mag_icon", null, null);
    if (searchView.findViewById(searchMagId) != null) {
        ImageView v = (ImageView) searchView.findViewById(searchMagId);
        v.setImageDrawable(null);
        v.setPadding(0, 0, 0, 0);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        params.setMargins(0, 0, 0, 0);
        v.setLayoutParams(params);
    }

    toolbar.setTitle(null);
    toolbar.setContentInsetsAbsolute(0, 0);
    toolbar.addView(searchView);

    return searchView;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.