获取列表视图的数组列表的原始位置

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