获取列表视图的数组列表的原始位置
Getting original position of arraylist for listview
我试图为列表视图创建一个搜索功能,并将意图 activity 用于结果。然而,随着搜索结果的出现,立场发生了变化。例如,
原始位置应为 0,1。但是搜索后,结果将位置转到3,4。
我尝试为此找到许多解决方案,但没有任何帮助。提前致谢!
这里是homefragment.java
package com.example.testtt;
import androidx.cardview.widget.CardView;
import androidx.fragment.app.Fragment;;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.SearchView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
public class HomeFragment extends Fragment implements View.OnClickListener {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_home, container, false);
//define
RelativeLayout drawerlayouthome;
ListView list;
ListViewAdapter adapter;
SearchView editsearch;
ArrayList<DoaSearchIndex> arrayList = new ArrayList<DoaSearchIndex>();
String[] doasearchindex = getActivity().getResources().getStringArray(R.array.doasearchindex);
//locatelistview
list = v.findViewById(R.id.searchlistview);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent;
switch (i){
case 0:
intent = new Intent(getActivity(), firstactivity.class);
startActivity(intent);
getId();
break;
case 1:
intent = new Intent(getActivity(), secondactivity.class);
startActivity(intent);
getId();
break;
}
list.setVisibility(View.INVISIBLE);
}
});
for (int i = 0; i < doasearchindex.length; i++) {
DoaSearchIndex doaSearchIndex = new DoaSearchIndex(doasearchindex[i]);
arrayList.add(doaSearchIndex);
}
//pass result to listviewadapter.class
adapter = new ListViewAdapter(this.getActivity(), arrayList);
//binds adapter to listview
list.setAdapter(adapter);
list.setVisibility(View.INVISIBLE);
//locatesearchview
editsearch = v.findViewById(R.id.searchview);
editsearch.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
if(TextUtils.isEmpty(newText)){
list.clearTextFilter();
adapter.filter("");
list.setVisibility(View.INVISIBLE);
} else {
adapter.filter(newText);
list.setVisibility(View.VISIBLE);
}
return true;
}
});
drawerlayouthome = v.findViewById(R.id.drawer_layouthome);
drawerlayouthome.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
list.setVisibility(View.INVISIBLE);
editsearch.clearFocus();
}
});
//definingcardview
CardView test = v.findViewById(R.id.test);
CardView testcard = v.findViewById(R.id.testcard);
//setcardviewlistener
test.setOnClickListener(this);
testcard.setOnClickListener(this);
return v;
}
@Override
public void onClick(View view) {
Intent i ;
switch (view.getId()) {
case R.id.test:
i = new Intent(getActivity(), test.class);
startActivity(i);
break;
case R.id.testcard:
i = new Intent(getActivity(), testcard.class);
startActivity(i);
break;
}
}
}
和ListViewAdapter.java
package com.example.testtt;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class ListViewAdapter extends BaseAdapter {
//Declare variables first
Context mContext;
LayoutInflater inflater;
private List<DoaSearchIndex> doaSearchIndexList = null;
private ArrayList<DoaSearchIndex> arrayList;
public ListViewAdapter(Context context, List<DoaSearchIndex> doaSearchIndexList) {
mContext = context;
this.doaSearchIndexList = doaSearchIndexList;
inflater = LayoutInflater.from(mContext);
this.arrayList = new ArrayList<DoaSearchIndex>();
this.arrayList.addAll(doaSearchIndexList);
}
public class ViewHolder {
TextView name;
}
@Override
public int getCount() {
return doaSearchIndexList.size();
}
@Override
public DoaSearchIndex getItem(int position) {
return doaSearchIndexList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
public View getView(final int position, View view, ViewGroup parent) {
final ViewHolder holder;
if (view == null) {
holder = new ViewHolder();
view = inflater.inflate(R.layout.listview_item, null);
// Locate the TextViews in listview_item.xml
holder.name = (TextView) view.findViewById(R.id.name);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
// Set the results into TextViews
holder.name.setText(doaSearchIndexList.get(position).getDoaSearchIndex());
return view;
}
// Filter Class
public void filter(String charText) {
charText = charText.toLowerCase(Locale.getDefault());
doaSearchIndexList.clear();
if (charText.length() == 0) {
doaSearchIndexList.addAll(arrayList);
} else {
for (DoaSearchIndex wp : arrayList) {
if (wp.getDoaSearchIndex().toLowerCase(Locale.getDefault()).contains(charText)) {
doaSearchIndexList.add(wp);
}
}
}
notifyDataSetChanged();
}
}
和DoaSearchIndex.java
public class DoaSearchIndex {
private String doaSearchIndex;
private int originalPosition;
public DoaSearchIndex(String doaSearchIndex) {
this.doaSearchIndex = doaSearchIndex;
}
public String getDoaSearchIndex() {
return this.doaSearchIndex;
}
private int getPosition() {
return this.originalPosition;
}
}
这是我的例子Fragment
:
public class MyDefaultFragment extends Fragment {
//Default items
public static ArrayList<MyItem> myItems = new ArrayList<>();
//Search filter
public static String filter = "";
public MyDefaultFragment(){
//require a empty constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.defaultfragment,container,false);
//I used a EditText instead of a SearchView
EditText editText = view.findViewById(R.id.filterEditText);
RecyclerView recyclerView = view.findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
recyclerView.setHasFixedSize(true);
//Checks for text change
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
filter = editText.getText().toString();
handler.postDelayed(this,500);
}
},500);
//Updates the Database every second | 1000 millisecond = 1 second
Handler update = new Handler();
update.postDelayed(new Runnable() {
@Override
public void run() {
new MyDatabase.AsyncTask(MyDatabase.getInstance(getContext())).execute();
update.postDelayed(this,1000);
}
},1000);
//Creates a new object in the Adapter.class
Adapter adapter = new Adapter();
myItems.clear();
//example items
myItems.add(new MyItem(R.drawable.bcn100, "firstActivity"));
myItems.add(new MyItem(R.drawable.ada100, "secondActivity"));
myItems.add(new MyItem(R.drawable.cos100, "otherActivity"));
recyclerView.setAdapter(adapter);
//Updates the Database on open the Fragment
new MyDatabase.AsyncTask(MyDatabase.getInstance(getContext())).execute();
//observe the LiveData<List<MyItem>> to an List<MyItem>
MyItemViewModel myItemViewModel = new ViewModelProvider(this).get(MyItemViewModel.class);
myItemViewModel.getAllItems().observe(getViewLifecycleOwner(), adapter::setItems);
return view;
}
}
这里是 Adapter
对应 CardView
:
public class Adapter extends RecyclerView.Adapter<Adapter.CardHolder> {
//Item list of the Adapter
public static List<MyItem> items = new ArrayList<>();
@NonNull
@Override
public CardHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
//CardView the name of the layout file smallcard
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.smallcard, parent, false);
CardHolder smallCardHolder = new CardHolder(itemView);
return smallCardHolder;
}
@Override
public void onBindViewHolder(@NonNull final CardHolder holder, int position) {
//get the item of the position
MyItem myItem = items.get(position);
int image = myItem.getMyImage();
String name = myItem.getMyName();
holder.imageView.setImageResource(image);
holder.textViewName.setText(name);
//onClickListener for the cardView
if(holder.cardView!= null) {
holder.cardView.setOnClickListener(v -> {
openActivity(holder.textViewName.getText().toString());
});
}
}
//You have to put here the method to open the activitys
public void openActivity(String name){
switch (name){
case "firstActivity":{
System.out.println("Open firstActivity");
break;
} case "secondActivity":{
System.out.println("Open secondActivity");
break;
} case "otherActivity":{
System.out.println("Open otherActivity");
break;
}
default:
break;
}
}
//Amount of items
@Override
public int getItemCount () {
return items.size();
}
public void setItems(List <MyItem> items) {
this.items = items;
notifyDataSetChanged();
}
//Card Holder
class CardHolder extends RecyclerView.ViewHolder {
private CardView cardView;
private ImageView imageView;
private TextView textViewName;
public CardHolder(@NonNull View itemView) {
super(itemView);
cardView = itemView.findViewById(R.id.card_View);
imageView = itemView.findViewById(R.id.card_Image);
textViewName = itemView.findViewById(R.id.card_Name);
}
}
}
这里是 Database
到 insert/delete CardView
//If you change the database schema you have to update the current version +1
@Database(entities = {MyItem.class},version = 1)
public abstract class MyDatabase extends RoomDatabase {
private static MyDatabase instance;
public abstract MyItemDao myItemDao();
public static synchronized MyDatabase getInstance(Context context){
//if the instance is null
if(instance == null){
instance = Room.databaseBuilder(context,MyDatabase.class,"my_Database")
.fallbackToDestructiveMigration()
.addCallback(callback)
.setAutoCloseTimeout(1, TimeUnit.SECONDS)
.build();
}
return instance;
}
private static Callback callback = new Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
new AsyncTask(instance).execute();
}
};
// The Async Task is deprecated you can use the Kotlin CoroutineAsyncTask instead of android.os.AsyncTask
// If you want to change it, this will help you
//
public static class AsyncTask extends android.os.AsyncTask<Void,Void,Void>{
MyItemDao myItemDao;
public AsyncTask(MyDatabase myDatabase){
this.myItemDao = myDatabase.myItemDao();
}
@Override
protected Void doInBackground(Void... voids) {
//default Items
List<MyItem> allDefaultItems = MyDefaultFragment.myItems;
//Current listed items in the RecyclerView
List<MyItem> allAdapterItems = Adapter.items;
String filter = MyDefaultFragment.filter;
int length = filter.length();
//Search method
if(length >0){
List<MyItem> deleteItems = new ArrayList<>();
List<MyItem> updateItems = new ArrayList<>();
allDefaultItems.forEach(myItem -> {
if(myItem.myName.toLowerCase().startsWith(filter)){
updateItems.add(myItem);
}else{
deleteItems.add(myItem);
}
});
myItemDao.delete(deleteItems);
myItemDao.insertAll(updateItems);
}else{
myItemDao.insertAll(allDefaultItems);
}
return null;
}
}
}
我的物品:
//If you want can change the tableName you have also change the name in the MyItemDao interface
@Entity(tableName = "myTable")
public class MyItem {
int myImage;
//A PrimaryKey is require for a Database
@PrimaryKey
@NonNull
String myName;
public MyItem(int myImage,String myName){
this.myImage = myImage;
this.myName = myName;
}
public int getMyImage() {
return myImage;
}
public void setMyImage(int myImage) {
this.myImage = myImage;
}
public String getMyName() {
return myName;
}
public void setMyName(String myName) {
this.myName = myName;
}
}
MyItemDao.java
:
@Dao
public interface MyItemDao {
//Select all data from myTable
@Query("Select * From myTable")
LiveData<List<MyItem>> getAllItems();
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAll(List<MyItem> myItems);
@Delete
void delete(List<MyItem> myItems);
@Query("Delete from myTable")
void deleteAllItems();
}
存储库:
public class MyItemRepository {
private LiveData<List<MyItem>> allItems;
private MyItemDao myItemDao;
public MyItemRepository(Application application){
MyDatabase myDatabase = MyDatabase.getInstance(application);
myItemDao = myDatabase.myItemDao();
allItems = myItemDao.getAllItems();
}
public void insertAll(List<MyItem> yItems){ new InsertAllItemsAsyncTask(myItemDao).execute(myItems); }
public void deleteItems(List<MyItem> myItems){
new DeleteItemListAsyncTask(myItemDao).execute(myItems);
}
public void deleteAllItems(){
new DeleteAllItemsAsyncTask(myItemDao).execute();
}
public LiveData<List<MyItem>> getAllItems(){
return allItems;
}
//Async tasks to put the items to the Database
private static class InsertAllItemsAsyncTask extends AsyncTask<List<MyItem>,Void,Void>{
MyItemDao myItemDao;
private InsertAllItemsAsyncTask(MyItemDao myItemDao){
this.myItemDao = myItemDao;
}
@Override
protected Void doInBackground(List<MyItem>... lists) {
myItemDao.insertAll(lists[0]);
return null;
}
}
private static class DeleteAllItemsAsyncTask extends AsyncTask<Void,Void,Void>{
MyItemDao myItemDao;
private DeleteAllItemsAsyncTask(MyItemDao myItemDao){
this.myItemDao = myItemDao;
}
@Override
protected Void doInBackground(Void... voids) {
myItemDao.deleteAllItems();
return null;
}
}
private static class DeleteItemListAsyncTask extends AsyncTask<List<MyItem>,Void,Void>{
MyItemDao myItemDao;
private DeleteItemListAsyncTask(MyItemDao myItemDao){
this.myItemDao = myItemDao;
}
@Override
protected Void doInBackground(List<MyItem>... myItems) {
myItemDao.delete(myItems[0]);
return null;
}
}
}
ViewModel
:
public class MyItemViewModel extends AndroidViewModel {
//LiveData is require for the RoomDatabase
private LiveData<List<MyItem>> allItems;
private MyItemRepository myItemRepository;
public MyItemViewModel(Application application){
super(application);
this.myItemRepository = new MyItemRepository(application);
allItems = myItemRepository.getAllItems();
}
public LiveData<List<MyItem>> getAllItems(){
return allItems;
}
public void insertAll(List<MyItem> myItems){
myItemRepository.insertAll(myItems);
}
//deletes a List of items
public void delete(List<MyItem> myItems){
myItemRepository.deleteItems(myItems);
}
public void deleteAllItems(){
myItemRepository.deleteAllItems();
}
}
CardView
我叫它smallcard.xml
:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_marginVertical="5dp"
android:backgroundTint="#ffffff"
android:id="@+id/card_View">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/card_Image"
android:layout_width="100px"
android:layout_height="100px"
android:layout_marginStart="10dp"
android:scaleType="fitCenter"/>
<TextView
android:id="@+id/card_Name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Name"
android:textColor="?attr/colorPrimary"
android:textSize="18sp"
android:textStyle="bold"/>
</RelativeLayout>
</androidx.cardview.widget.CardView>
</RelativeLayout>
测试Fragment.xml
:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MyDefaultFragment"
android:background="#ffffff">
<EditText
android:id="@+id/filterEditText"
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="40dp"
/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:layout_below="@id/filterEditText"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
/>
</RelativeLayout>
一些 build.gradle(Module)
implementations
:
dependencies{
implementation 'androidx.room:room-runtime:2.3.0'
annotationProcessor 'androidx.room:room-compiler:2.3.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.3.1'
implementation 'androidx.lifecycle:lifecycle-livedata:2.3.1'
annotationProcessor 'androidx.lifecycle:lifecycle-compiler:2.3.1'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
...
}
您将在代码中找到更多信息作为注释。
更新
此外,我在 github 上为您提供了整个项目。单击卡片后,我添加了不同的意图。即使您正在搜索并且位置已更改,它也会为同一张卡片打开相同的Fragment
。
我试图为列表视图创建一个搜索功能,并将意图 activity 用于结果。然而,随着搜索结果的出现,立场发生了变化。例如, 原始位置应为 0,1。但是搜索后,结果将位置转到3,4。 我尝试为此找到许多解决方案,但没有任何帮助。提前致谢!
这里是homefragment.java
package com.example.testtt;
import androidx.cardview.widget.CardView;
import androidx.fragment.app.Fragment;;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.SearchView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
public class HomeFragment extends Fragment implements View.OnClickListener {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_home, container, false);
//define
RelativeLayout drawerlayouthome;
ListView list;
ListViewAdapter adapter;
SearchView editsearch;
ArrayList<DoaSearchIndex> arrayList = new ArrayList<DoaSearchIndex>();
String[] doasearchindex = getActivity().getResources().getStringArray(R.array.doasearchindex);
//locatelistview
list = v.findViewById(R.id.searchlistview);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent;
switch (i){
case 0:
intent = new Intent(getActivity(), firstactivity.class);
startActivity(intent);
getId();
break;
case 1:
intent = new Intent(getActivity(), secondactivity.class);
startActivity(intent);
getId();
break;
}
list.setVisibility(View.INVISIBLE);
}
});
for (int i = 0; i < doasearchindex.length; i++) {
DoaSearchIndex doaSearchIndex = new DoaSearchIndex(doasearchindex[i]);
arrayList.add(doaSearchIndex);
}
//pass result to listviewadapter.class
adapter = new ListViewAdapter(this.getActivity(), arrayList);
//binds adapter to listview
list.setAdapter(adapter);
list.setVisibility(View.INVISIBLE);
//locatesearchview
editsearch = v.findViewById(R.id.searchview);
editsearch.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
if(TextUtils.isEmpty(newText)){
list.clearTextFilter();
adapter.filter("");
list.setVisibility(View.INVISIBLE);
} else {
adapter.filter(newText);
list.setVisibility(View.VISIBLE);
}
return true;
}
});
drawerlayouthome = v.findViewById(R.id.drawer_layouthome);
drawerlayouthome.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
list.setVisibility(View.INVISIBLE);
editsearch.clearFocus();
}
});
//definingcardview
CardView test = v.findViewById(R.id.test);
CardView testcard = v.findViewById(R.id.testcard);
//setcardviewlistener
test.setOnClickListener(this);
testcard.setOnClickListener(this);
return v;
}
@Override
public void onClick(View view) {
Intent i ;
switch (view.getId()) {
case R.id.test:
i = new Intent(getActivity(), test.class);
startActivity(i);
break;
case R.id.testcard:
i = new Intent(getActivity(), testcard.class);
startActivity(i);
break;
}
}
}
和ListViewAdapter.java
package com.example.testtt;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class ListViewAdapter extends BaseAdapter {
//Declare variables first
Context mContext;
LayoutInflater inflater;
private List<DoaSearchIndex> doaSearchIndexList = null;
private ArrayList<DoaSearchIndex> arrayList;
public ListViewAdapter(Context context, List<DoaSearchIndex> doaSearchIndexList) {
mContext = context;
this.doaSearchIndexList = doaSearchIndexList;
inflater = LayoutInflater.from(mContext);
this.arrayList = new ArrayList<DoaSearchIndex>();
this.arrayList.addAll(doaSearchIndexList);
}
public class ViewHolder {
TextView name;
}
@Override
public int getCount() {
return doaSearchIndexList.size();
}
@Override
public DoaSearchIndex getItem(int position) {
return doaSearchIndexList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
public View getView(final int position, View view, ViewGroup parent) {
final ViewHolder holder;
if (view == null) {
holder = new ViewHolder();
view = inflater.inflate(R.layout.listview_item, null);
// Locate the TextViews in listview_item.xml
holder.name = (TextView) view.findViewById(R.id.name);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
// Set the results into TextViews
holder.name.setText(doaSearchIndexList.get(position).getDoaSearchIndex());
return view;
}
// Filter Class
public void filter(String charText) {
charText = charText.toLowerCase(Locale.getDefault());
doaSearchIndexList.clear();
if (charText.length() == 0) {
doaSearchIndexList.addAll(arrayList);
} else {
for (DoaSearchIndex wp : arrayList) {
if (wp.getDoaSearchIndex().toLowerCase(Locale.getDefault()).contains(charText)) {
doaSearchIndexList.add(wp);
}
}
}
notifyDataSetChanged();
}
}
和DoaSearchIndex.java
public class DoaSearchIndex {
private String doaSearchIndex;
private int originalPosition;
public DoaSearchIndex(String doaSearchIndex) {
this.doaSearchIndex = doaSearchIndex;
}
public String getDoaSearchIndex() {
return this.doaSearchIndex;
}
private int getPosition() {
return this.originalPosition;
}
}
这是我的例子Fragment
:
public class MyDefaultFragment extends Fragment {
//Default items
public static ArrayList<MyItem> myItems = new ArrayList<>();
//Search filter
public static String filter = "";
public MyDefaultFragment(){
//require a empty constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.defaultfragment,container,false);
//I used a EditText instead of a SearchView
EditText editText = view.findViewById(R.id.filterEditText);
RecyclerView recyclerView = view.findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
recyclerView.setHasFixedSize(true);
//Checks for text change
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
filter = editText.getText().toString();
handler.postDelayed(this,500);
}
},500);
//Updates the Database every second | 1000 millisecond = 1 second
Handler update = new Handler();
update.postDelayed(new Runnable() {
@Override
public void run() {
new MyDatabase.AsyncTask(MyDatabase.getInstance(getContext())).execute();
update.postDelayed(this,1000);
}
},1000);
//Creates a new object in the Adapter.class
Adapter adapter = new Adapter();
myItems.clear();
//example items
myItems.add(new MyItem(R.drawable.bcn100, "firstActivity"));
myItems.add(new MyItem(R.drawable.ada100, "secondActivity"));
myItems.add(new MyItem(R.drawable.cos100, "otherActivity"));
recyclerView.setAdapter(adapter);
//Updates the Database on open the Fragment
new MyDatabase.AsyncTask(MyDatabase.getInstance(getContext())).execute();
//observe the LiveData<List<MyItem>> to an List<MyItem>
MyItemViewModel myItemViewModel = new ViewModelProvider(this).get(MyItemViewModel.class);
myItemViewModel.getAllItems().observe(getViewLifecycleOwner(), adapter::setItems);
return view;
}
}
这里是 Adapter
对应 CardView
:
public class Adapter extends RecyclerView.Adapter<Adapter.CardHolder> {
//Item list of the Adapter
public static List<MyItem> items = new ArrayList<>();
@NonNull
@Override
public CardHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
//CardView the name of the layout file smallcard
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.smallcard, parent, false);
CardHolder smallCardHolder = new CardHolder(itemView);
return smallCardHolder;
}
@Override
public void onBindViewHolder(@NonNull final CardHolder holder, int position) {
//get the item of the position
MyItem myItem = items.get(position);
int image = myItem.getMyImage();
String name = myItem.getMyName();
holder.imageView.setImageResource(image);
holder.textViewName.setText(name);
//onClickListener for the cardView
if(holder.cardView!= null) {
holder.cardView.setOnClickListener(v -> {
openActivity(holder.textViewName.getText().toString());
});
}
}
//You have to put here the method to open the activitys
public void openActivity(String name){
switch (name){
case "firstActivity":{
System.out.println("Open firstActivity");
break;
} case "secondActivity":{
System.out.println("Open secondActivity");
break;
} case "otherActivity":{
System.out.println("Open otherActivity");
break;
}
default:
break;
}
}
//Amount of items
@Override
public int getItemCount () {
return items.size();
}
public void setItems(List <MyItem> items) {
this.items = items;
notifyDataSetChanged();
}
//Card Holder
class CardHolder extends RecyclerView.ViewHolder {
private CardView cardView;
private ImageView imageView;
private TextView textViewName;
public CardHolder(@NonNull View itemView) {
super(itemView);
cardView = itemView.findViewById(R.id.card_View);
imageView = itemView.findViewById(R.id.card_Image);
textViewName = itemView.findViewById(R.id.card_Name);
}
}
}
这里是 Database
到 insert/delete CardView
//If you change the database schema you have to update the current version +1
@Database(entities = {MyItem.class},version = 1)
public abstract class MyDatabase extends RoomDatabase {
private static MyDatabase instance;
public abstract MyItemDao myItemDao();
public static synchronized MyDatabase getInstance(Context context){
//if the instance is null
if(instance == null){
instance = Room.databaseBuilder(context,MyDatabase.class,"my_Database")
.fallbackToDestructiveMigration()
.addCallback(callback)
.setAutoCloseTimeout(1, TimeUnit.SECONDS)
.build();
}
return instance;
}
private static Callback callback = new Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
new AsyncTask(instance).execute();
}
};
// The Async Task is deprecated you can use the Kotlin CoroutineAsyncTask instead of android.os.AsyncTask
// If you want to change it, this will help you
//
public static class AsyncTask extends android.os.AsyncTask<Void,Void,Void>{
MyItemDao myItemDao;
public AsyncTask(MyDatabase myDatabase){
this.myItemDao = myDatabase.myItemDao();
}
@Override
protected Void doInBackground(Void... voids) {
//default Items
List<MyItem> allDefaultItems = MyDefaultFragment.myItems;
//Current listed items in the RecyclerView
List<MyItem> allAdapterItems = Adapter.items;
String filter = MyDefaultFragment.filter;
int length = filter.length();
//Search method
if(length >0){
List<MyItem> deleteItems = new ArrayList<>();
List<MyItem> updateItems = new ArrayList<>();
allDefaultItems.forEach(myItem -> {
if(myItem.myName.toLowerCase().startsWith(filter)){
updateItems.add(myItem);
}else{
deleteItems.add(myItem);
}
});
myItemDao.delete(deleteItems);
myItemDao.insertAll(updateItems);
}else{
myItemDao.insertAll(allDefaultItems);
}
return null;
}
}
}
我的物品:
//If you want can change the tableName you have also change the name in the MyItemDao interface
@Entity(tableName = "myTable")
public class MyItem {
int myImage;
//A PrimaryKey is require for a Database
@PrimaryKey
@NonNull
String myName;
public MyItem(int myImage,String myName){
this.myImage = myImage;
this.myName = myName;
}
public int getMyImage() {
return myImage;
}
public void setMyImage(int myImage) {
this.myImage = myImage;
}
public String getMyName() {
return myName;
}
public void setMyName(String myName) {
this.myName = myName;
}
}
MyItemDao.java
:
@Dao
public interface MyItemDao {
//Select all data from myTable
@Query("Select * From myTable")
LiveData<List<MyItem>> getAllItems();
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAll(List<MyItem> myItems);
@Delete
void delete(List<MyItem> myItems);
@Query("Delete from myTable")
void deleteAllItems();
}
存储库:
public class MyItemRepository {
private LiveData<List<MyItem>> allItems;
private MyItemDao myItemDao;
public MyItemRepository(Application application){
MyDatabase myDatabase = MyDatabase.getInstance(application);
myItemDao = myDatabase.myItemDao();
allItems = myItemDao.getAllItems();
}
public void insertAll(List<MyItem> yItems){ new InsertAllItemsAsyncTask(myItemDao).execute(myItems); }
public void deleteItems(List<MyItem> myItems){
new DeleteItemListAsyncTask(myItemDao).execute(myItems);
}
public void deleteAllItems(){
new DeleteAllItemsAsyncTask(myItemDao).execute();
}
public LiveData<List<MyItem>> getAllItems(){
return allItems;
}
//Async tasks to put the items to the Database
private static class InsertAllItemsAsyncTask extends AsyncTask<List<MyItem>,Void,Void>{
MyItemDao myItemDao;
private InsertAllItemsAsyncTask(MyItemDao myItemDao){
this.myItemDao = myItemDao;
}
@Override
protected Void doInBackground(List<MyItem>... lists) {
myItemDao.insertAll(lists[0]);
return null;
}
}
private static class DeleteAllItemsAsyncTask extends AsyncTask<Void,Void,Void>{
MyItemDao myItemDao;
private DeleteAllItemsAsyncTask(MyItemDao myItemDao){
this.myItemDao = myItemDao;
}
@Override
protected Void doInBackground(Void... voids) {
myItemDao.deleteAllItems();
return null;
}
}
private static class DeleteItemListAsyncTask extends AsyncTask<List<MyItem>,Void,Void>{
MyItemDao myItemDao;
private DeleteItemListAsyncTask(MyItemDao myItemDao){
this.myItemDao = myItemDao;
}
@Override
protected Void doInBackground(List<MyItem>... myItems) {
myItemDao.delete(myItems[0]);
return null;
}
}
}
ViewModel
:
public class MyItemViewModel extends AndroidViewModel {
//LiveData is require for the RoomDatabase
private LiveData<List<MyItem>> allItems;
private MyItemRepository myItemRepository;
public MyItemViewModel(Application application){
super(application);
this.myItemRepository = new MyItemRepository(application);
allItems = myItemRepository.getAllItems();
}
public LiveData<List<MyItem>> getAllItems(){
return allItems;
}
public void insertAll(List<MyItem> myItems){
myItemRepository.insertAll(myItems);
}
//deletes a List of items
public void delete(List<MyItem> myItems){
myItemRepository.deleteItems(myItems);
}
public void deleteAllItems(){
myItemRepository.deleteAllItems();
}
}
CardView
我叫它smallcard.xml
:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_marginVertical="5dp"
android:backgroundTint="#ffffff"
android:id="@+id/card_View">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/card_Image"
android:layout_width="100px"
android:layout_height="100px"
android:layout_marginStart="10dp"
android:scaleType="fitCenter"/>
<TextView
android:id="@+id/card_Name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Name"
android:textColor="?attr/colorPrimary"
android:textSize="18sp"
android:textStyle="bold"/>
</RelativeLayout>
</androidx.cardview.widget.CardView>
</RelativeLayout>
测试Fragment.xml
:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MyDefaultFragment"
android:background="#ffffff">
<EditText
android:id="@+id/filterEditText"
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="40dp"
/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:layout_below="@id/filterEditText"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
/>
</RelativeLayout>
一些 build.gradle(Module)
implementations
:
dependencies{
implementation 'androidx.room:room-runtime:2.3.0'
annotationProcessor 'androidx.room:room-compiler:2.3.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.3.1'
implementation 'androidx.lifecycle:lifecycle-livedata:2.3.1'
annotationProcessor 'androidx.lifecycle:lifecycle-compiler:2.3.1'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
...
}
您将在代码中找到更多信息作为注释。
更新
此外,我在 github 上为您提供了整个项目。单击卡片后,我添加了不同的意图。即使您正在搜索并且位置已更改,它也会为同一张卡片打开相同的Fragment
。