Intro
Sayangnya, tidak ada cara untuk menyetel SearchView
gaya bidang teks menggunakan tema, gaya, dan warisan dalam XML seperti yang dapat Anda lakukan dengan latar belakang item di tarik-turun ActionBar . Hal ini karena selectableItemBackground
terdaftar sebagai styleable di R.stylable
, sedangkan searchViewTextField
(atribut tema yang kita tertarik) tidak. Jadi, kami tidak dapat mengaksesnya dengan mudah dari dalam sumber daya XML (Anda akan mendapatkan No resource found that matches the given name: attr 'android:searchViewTextField'
kesalahan).
Mengatur latar belakang bidang teks SearchView dari kode
Jadi, satu-satunya cara untuk mengganti latar belakang SearchView
bidang teks dengan benar adalah dengan masuk ke bagian dalamnya, memperoleh akses ke tampilan yang memiliki latar belakang berdasarkan searchViewTextField
dan menetapkan milik kita sendiri.
CATATAN: Solusi di bawah ini hanya bergantung pada id ( android:id/search_plate
) elemen di dalamnya SearchView
, jadi ini lebih independen dari versi SDK daripada traversal turunan (misalnya menggunakan searchView.getChildAt(0)
untuk mendapatkan tampilan yang benar di dalamnya SearchView
), tetapi ini bukan anti peluru. Terutama jika beberapa pabrikan memutuskan untuk menerapkan ulang internal dari SearchView
dan elemen dengan id yang disebutkan di atas tidak ada - kode tidak akan berfungsi.
Di SDK, latar belakang untuk bidang teks di SearchView
dideklarasikan melalui sembilan tambalan , jadi kami akan melakukannya dengan cara yang sama. Anda dapat menemukan gambar png asli di direktori drawable-mdpi dari repositori git Android . Kami tertarik pada dua gambar. Satu untuk status ketika bidang teks dipilih (dinamai textfield_search_selected_holo_light.9.png ) dan satu untuk tempat yang bukan (dinamai textfield_search_default_holo_light.9.png ).
Sayangnya, Anda harus membuat salinan lokal dari kedua gambar tersebut, meskipun Anda hanya ingin menyesuaikan status fokus . Ini karena textfield_search_default_holo_light
tidak ada di R.drawable . Oleh karena itu, ini tidak mudah diakses melalui @android:drawable/textfield_search_default_holo_light
, yang dapat digunakan dalam selektor yang ditunjukkan di bawah, alih-alih merujuk drawable lokal.
CATATAN: Saya menggunakan tema Holo Light sebagai dasar, tetapi Anda dapat melakukan hal yang sama dengan Holo Dark . Tampaknya tidak ada perbedaan nyata dalam memilih negara 9-patch antara Cahaya dan gelap tema. Namun, ada perbedaan dalam 9-patch untuk status default (lihat Terang vs Gelap ). Jadi, mungkin tidak perlu membuat salinan lokal 9-patch untuk status yang dipilih , untuk tema Gelap dan Terang (dengan asumsi Anda ingin menangani keduanya, dan membuat keduanya terlihat sama seperti di Tema Holo ). Cukup buat satu salinan lokal dan gunakan didrawable pemilih untuk kedua tema.
Sekarang, Anda harus mengedit sembilan-patch yang diunduh sesuai kebutuhan Anda (yaitu, mengubah warna biru menjadi merah). Anda dapat melihat file menggunakan alat draw 9-patch untuk memeriksa apakah sudah ditentukan dengan benar setelah Anda mengedit.
Saya telah mengedit file menggunakan GIMP dengan alat pensil satu piksel (cukup mudah) tetapi Anda mungkin akan menggunakan alat Anda sendiri. Inilah 9-patch saya yang disesuaikan untuk keadaan terfokus :
CATATAN: Untuk kesederhanaan, saya hanya menggunakan gambar untuk kepadatan mdpi . Anda harus membuat 9-patch untuk beberapa kepadatan layar jika Anda menginginkan hasil terbaik pada perangkat apa pun. Gambar untuk Holo SearchView
dapat ditemukan dalam mdpi , hdpi , dan xhdpi drawable .
Sekarang, kita perlu membuat pemilih drawable, sehingga gambar yang tepat ditampilkan berdasarkan status tampilan. Buat file res/drawable/texfield_searchview_holo_light.xml
dengan konten berikut:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true"
android:drawable="@drawable/textfield_search_selected_holo_light" />
<item android:drawable="@drawable/textfield_search_default_holo_light" />
</selector>
Kami akan menggunakan drawable yang dibuat di atas untuk mengatur latar belakang untuk LinearLayout
tampilan yang menampung bidang teks di dalamnya SearchView
- id-nya adalah android:id/search_plate
. Jadi, inilah cara melakukan ini dengan cepat dalam kode, saat membuat menu opsi:
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
// Getting SearchView from XML layout by id defined there - my_search_view in this case
SearchView searchView = (SearchView) menu.findItem(R.id.my_search_view).getActionView();
// Getting id for 'search_plate' - the id is part of generate R file,
// so we have to get id on runtime.
int searchPlateId = searchView.getContext().getResources().getIdentifier("android:id/search_plate", null, null);
// Getting the 'search_plate' LinearLayout.
View searchPlate = searchView.findViewById(searchPlateId);
// Setting background of 'search_plate' to earlier defined drawable.
searchPlate.setBackgroundResource(R.drawable.textfield_searchview_holo_light);
return super.onCreateOptionsMenu(menu);
}
}
Efek akhir
Berikut tangkapan layar dari hasil akhirnya:
Bagaimana saya bisa melakukan ini
Saya pikir ada baiknya mengukur bagaimana saya sampai ini, sehingga pendekatan ini dapat digunakan saat menyesuaikan tampilan lain.
Memeriksa tata letak tampilan
Saya telah memeriksa tampilan SearchView
tata letak. Di kontraktor SearchView, seseorang dapat menemukan baris yang mengembangkan tata letak:
inflater.inflate(R.layout.search_view, this, true);
Sekarang kita tahu bahwa SearchView
layout dalam file bernama res/layout/search_view.xml
. Melihat ke dalam search_view.xml kita dapat menemukan LinearLayout
elemen dalam (dengan id search_plate
) yang ada android.widget.SearchView$SearchAutoComplete
di dalamnya (terlihat seperti bidang teks tampilan pencarian kita):
<LinearLayout
android:id="@+id/search_plate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:orientation="horizontal"
android:background="?android:attr/searchViewTextField">
Sekarang, kita sekarang latar belakang diatur berdasarkan searchViewTextField
atribut tema saat ini .
Investigasi atribut (apakah mudah diatur?)
Untuk memeriksa bagaimana searchViewTextField
atribut disetel, kami menyelidiki res / values / themes.xml . Ada sekelompok atribut yang terkait SearchView
secara default Theme
:
<style name="Theme">
<!-- (...other attributes present here...) -->
<!-- SearchView attributes -->
<item name="searchDropdownBackground">@android:drawable/spinner_dropdown_background</item>
<item name="searchViewTextField">@drawable/textfield_searchview_holo_dark</item>
<item name="searchViewTextFieldRight">@drawable/textfield_searchview_right_holo_dark</item>
<item name="searchViewCloseIcon">@android:drawable/ic_clear</item>
<item name="searchViewSearchIcon">@android:drawable/ic_search</item>
<item name="searchViewGoIcon">@android:drawable/ic_go</item>
<item name="searchViewVoiceIcon">@android:drawable/ic_voice_search</item>
<item name="searchViewEditQuery">@android:drawable/ic_commit_search_api_holo_dark</item>
<item name="searchViewEditQueryBackground">?attr/selectableItemBackground</item>
Kami melihat bahwa untuk tema default nilainya adalah @drawable/textfield_searchview_holo_dark
. Untuk Theme.Light
nilai juga diatur dalam file itu .
Sekarang, akan sangat bagus jika atribut ini dapat diakses melalui R.styleable , tetapi sayangnya tidak. Sebagai perbandingan, lihat atribut tema lain yang ada di themes.xml dan R.attr seperti textAppearance atau selectableItemBackground . Jika searchViewTextField
ada di R.attr
(dan R.stylable
) kami cukup menggunakan pemilih drawable kami saat menentukan tema untuk seluruh aplikasi kami dalam XML. Sebagai contoh:
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="AppTheme" parent="android:Theme.Light">
<item name="android:searchViewTextField">@drawable/textfield_searchview_holo_light</item>
</style>
</resources>
Apa yang harus diubah?
Sekarang kita tahu, bahwa kita harus mengakses search_plate
melalui kode. Namun, kami masih belum tahu bagaimana seharusnya tampilannya. Singkatnya, kami mencari drawable yang digunakan sebagai nilai dalam tema default: textfield_searchview_holo_dark.xml dan textfield_searchview_holo_light.xml . Melihat konten, kita melihat bahwa drawable selector
merujuk pada dua drawable lainnya (yang nantinya merupakan 9-patch) berdasarkan status tampilan. Anda dapat menemukan agregat 9-patch drawable dari (hampir) semua versi Android di androiddrawables.com
Menyesuaikan
Kami mengenali garis biru di salah satu dari 9-patch , jadi kami membuat salinan lokalnya dan mengubah warna sesuai keinginan.