我是编码新手。我正在尝试实现一个应该更新 GridView 的 SearchView 小部件,但它不起作用。当我在搜索字段中输入内容时,没有任何反应。如果我点击搜索按钮,则没有任何反应。你能帮帮我吗?
这是主要活动:
public class MainActivity extends AppCompatActivity {
private static Context mainContext;
private FragmentDataSaver mDataSaver;
private static final String DATA_SAVER_TAG = "DATA_SAVER";
private View mDecorView;
public ArrayList<Movies> mMovies;
WallAdapter wallAdapter;
GridView gridView;
public static Context getContext(){
return mainContext;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDecorView = getWindow().getDecorView();
mainContext = getApplicationContext();
setContentView(R.layout.activity_main);
Toolbar myToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(myToolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
FragmentManager fm = getSupportFragmentManager();
mDataSaver = (FragmentDataSaver)fm.findFragmentByTag(DATA_SAVER_TAG);
if(mDataSaver == null){
mDataSaver = new FragmentDataSaver();
fm.beginTransaction().add(mDataSaver, DATA_SAVER_TAG).commit();
mMovies = DatabaseProva.creaDatabaseProva();
mDataSaver.setData(mMovies);
} else {
mMovies = mDataSaver.getData();
}
gridView = (GridView)findViewById(R.id.gridview_layout);
/*if(savedInstanceState == null){
mMovies = DatabaseProva.creaDatabaseProva();
} else {
mMovies = savedInstanceState.getParcelableArrayList("tempMovies");
}*/
wallAdapter = new WallAdapter(this, mMovies);
gridView.setAdapter(wallAdapter);
handleIntent(getIntent());
}
@Override
protected void onNewIntent(Intent intent) {
handleIntent(intent);
}
private void handleIntent(Intent intent) {
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
//use the query to search your data somehow
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.toolbar_menu, menu);
MenuItem searchMenu = menu.findItem(R.id.search_view);
// Get the SearchView and set the searchable configuration
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
android.widget.SearchView searchView = (android.widget.SearchView) searchMenu.getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setIconifiedByDefault(false); // Do not iconify the widget; expand it by default
searchView.setOnQueryTextListener(new android.widget.SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
wallAdapter.getFilter().filter(newText);
return false;
}
});
return super.onCreateOptionsMenu(menu);
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(hasFocus){
mDecorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
}
/*@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelableArrayList("tempMovies", wallAdapter.getItems());
}*/
适配器(墙上适配器(:
public class WallAdapter extends ArrayAdapter<Movies> implements Filterable{
private ArrayList<Movies> tempMovies = new ArrayList<Movies>();
public WallAdapter(Context context, ArrayList movies) {
super(context, 0, movies);
setItems(movies);
}
public ArrayList<Movies> getMovies() {
return tempMovies;
}
public void setItems(ArrayList<Movies> movies) {
this.tempMovies = movies;
}
public ArrayList<Movies> getItems() {
return tempMovies;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null){
convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_layout, parent, false);
holder = new ViewHolder();
holder.mImage = (ImageView) convertView.findViewById(R.id.item_view);
holder.mImage.setScaleType(ImageView.ScaleType.CENTER_CROP);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
final Movies currentMovie = getItem(position);
holder.mImage.setImageBitmap(currentMovie.getImage());
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getContext(), SchedaFilm.class);
intent.putExtra("titolo", currentMovie.getTitolo());
intent.putExtra("locandina", currentMovie.getIdLocandina());
intent.putExtra("trama", currentMovie.getTrama());
intent.putExtra("regia", currentMovie.getRegia());
intent.putExtra("anno", currentMovie.getAnno());
intent.putExtra("genere", currentMovie.getGenere());
getContext().startActivity(intent);
}
});
return convertView;
}
Filter filter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
ArrayList<Movies> tempList = new ArrayList<>();
//constraint is the result from text you want to filter against.
//objects is your data set you will filter from
if(constraint != null || constraint.length() == 0) {
// No filter implemented we return all the list
filterResults.values = tempMovies;
filterResults.count = tempMovies.size();
} else {
for(Movies m : tempMovies){
if(m.toString().toLowerCase().contains(constraint.toString().toLowerCase())){
tempList.add(m);
}
}
filterResults.values = tempList;
filterResults.count = tempList.size();
}
return filterResults;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if(results.count == 0){
notifyDataSetInvalidated();
} else {
tempMovies = (ArrayList<Movies>) results.values;
notifyDataSetChanged();
}
}
};
@NonNull
@Override
public Filter getFilter() {
return filter;
}
static class ViewHolder{
private ImageView mImage;
public Context getContext(){
return mImage.getContext();
}
}
我的清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest package="arca.mitty.com.arcagridview"
xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
<activity android:name=".MainActivity"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="android.intent.action.SEARCH" />
<meta-data android:name="android.app.searchable"
android:resource="@xml/searchable"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".SchedaFilm"
android:parentActivityName=".MainActivity">
</activity>
</application>
</manifest>
可搜索的 xml 文件:
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/app_label"
android:hint="@string/search_hint" >
</searchable>
这是电影类:
public class Movies implements Parcelable{
private String mTitolo;
private String mGenere;
private Bitmap mLocandina;
private Bitmap mLocandinaBig;
private int mAnno;
private int mIdLocandina;
private String mTrama = "Seduto sulla panchina ad un bus-stop di Savannah, " +
"Forrest Gump ricorda la sua infanzia di bimbo con problemi mentali e fisici. " +
"Solo la mamma lo accetta per quello che è, e solo la piccola Jenny Curran lo fa sedere accanto a sé sull'autobus della scuola. " +
"Sarà lei a incitarlo, per fuggire a tre compagnetti violenti, a correre, liberando così le gambe dalla protesi. " +
"Attraverso trent'anni di storia americana vista con gli occhi della semplicità e dell'innocenza, Forrest diventa un campione universitario di football, " +
"mentre è sempre più innamorato di Jenny che però lo considera un fratello. Assiste ai disordini razziali in Alabama ed incontra Kennedy poco prima dell'assassinio. " +
"Si arruola quindi nell'esercito, dove fa amicizia con il nero Bubba, un pescatore di gamberi che gli comunica la sua passione. " +
"Dopo un fugace incontro con Jenny che canta a Memphis, Gump va a combattere in Vietnam.";
private String mRegia = "Bino Cicogna";
//Constructor
public Movies (String titolo, String genere, int locandina, int anno){
mTitolo = titolo;
mGenere = genere;
mIdLocandina = locandina;
mLocandina = decodeSampledBitmapFromResource(MainActivity.getContext().getResources(), locandina, 90, 135);
mAnno = anno;
}
protected Movies(Parcel in) {
mTitolo = in.readString();
mGenere = in.readString();
mLocandina = in.readParcelable(Bitmap.class.getClassLoader());
mAnno = in.readInt();
}
public static final Creator<Movies> CREATOR = new Creator<Movies>() {
@Override
public Movies createFromParcel(Parcel in) {
return new Movies(in);
}
@Override
public Movies[] newArray(int size) {
return new Movies[size];
}
};
public String getTitolo() {
return mTitolo;
}
public String getGenere() {
return mGenere;
}
public int getIdLocandina(){
return mIdLocandina;
}
public Bitmap getImage() {
return mLocandina;
}
public int getAnno() {
return mAnno;
}
public String getTrama(){
return mTrama;
}
public String getRegia(){
return mRegia;
}
public String toString(){
String s = "";
s = getTitolo() + " " + getGenere() + " " + getRegia() + " " + getAnno();
return s;
}
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) >= reqHeight
&& (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mTitolo);
dest.writeString(mGenere);
dest.writeParcelable(mLocandina, flags);
dest.writeInt(mAnno);
}
}
在过滤器中,您正在执行以下操作:
if (m.toString().toLowerCase().contains(constraint.toString().toLowerCase())) {
tempList.add(m);
}
确保返回m.toString()
实际包含电影名称的值,如果没有,该条件将始终false
且tempList
为空,并将执行下一个代码:
if (results.count == 0) {
notifyDataSetInvalidated();
}
,经过多次尝试,我找到了解决方案。
显然,存在逻辑错误:在"过滤器"中,我更新了错误的电影 ArrayList。适配器用于在我的应用程序中构建 GridView 的适配器是"tempMovies"ArrayList。在"过滤器"中,我使用"tempList",然后更新"filterResults",但从未更新"tempMovies"。即使在"getFilter"方法中。
此外,我发现了一种更容易理解和应用的"过滤器"方法。我正在使用它,它工作得很好。
这是代码:
public void filter(CharSequence text){
String query = text.toString().toLowerCase();
tempMovies.clear();
if(text.length() == 0){
tempMovies.addAll(originalMoviesList);
} else{
for(Movies m : originalMoviesList){
if(m.toString().toLowerCase().contains(query)){
tempMovies.add(m);
}
}
}
notifyDataSetChanged();
}
我在这个网站上找到了它:http://www.androidbegin.com/tutorial/android-search-listview-using-filter/
最后,再次感谢所有试图提供帮助的人。我希望我的经验对其他人有用。