获取列表视图的arraylist的原始位置

Posted

技术标签:

【中文标题】获取列表视图的arraylist的原始位置【英文标题】:Getting original position of arraylist for listview 【发布时间】:2021-09-29 23:55:46 【问题描述】:

我试图为列表视图创建一个搜索功能,并将意图活动放在结果中。但是,随着搜索结果的出现,位置发生了变化。例如, 原始位置应为 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;
    


【问题讨论】:

请尝试在 ViewHolder 类中使用位置变量,并在从 getview 创建对象时对其进行更新...然后尝试通过在 getview 中使用 viewholder 实例来使用该位置 ....如果您需要此点击然后你可以在视图中使用 setag 和 gettag ..可以帮助你 您在代码中的什么位置记录这些位置? @Ghanshyam 你能举个例子吗? 你能试试我的答案吗?如果您跟随,即使您在 recyclerView 中搜索特定项目,您的位置也会被记住。请告诉我 【参考方案1】:

这是我的例子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;
    


这是AdapterCardView

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);

        
    


这是插入/删除CardViewDatabase

        //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
    // https://***.com/questions/68136577/how-to-replace-asynctask-in-this-android-code/68137304#68137304
    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_
                android:orientation="horizontal"
                android:layout_>
    
    <androidx.cardview.widget.CardView
            android:layout_
            android:layout_
            android:layout_marginHorizontal="10dp"
            android:layout_marginVertical="5dp"
            android:backgroundTint="#ffffff"
            android:id="@+id/card_View">

        <RelativeLayout
                android:layout_
                android:layout_>

            <ImageView
                    android:id="@+id/card_Image"
                    android:layout_
                    android:layout_
                    android:layout_marginStart="10dp"
                    android:scaleType="fitCenter"/>

                <TextView
                        android:id="@+id/card_Name"
                        android:layout_
                        android:layout_
                        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_
                android:layout_
                tools:context=".MyDefaultFragment"
                android:background="#ffffff">

    <EditText
            android:id="@+id/filterEditText"
            android:layout_marginTop="10dp"
            android:layout_
            android:layout_
    />

    <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_
            android:layout_
            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'
...

您将在代码中以 cmets 的形式找到更多信息。


更新

此外,我在github 上为您提供整个项目。单击卡片后,我添加了不同的意图。即使您正在搜索并且位置发生变化,它也会为同一张卡片打开相同的Fragment

【讨论】:

对不起,先生回复晚了,我正在努力找出答案。您能否详细说明如何使用此方法?由于我是初学者,我很抱歉这些问题。但真的很想了解它。 好的,不用担心。让我命名您需要创建和复制其中代码的类和 xml 文件。我建议打开一个新的空项目。使用上面的代码,您可以重现整个项目。然后尝试用 cmets 来理解它。这将是初学者的最佳方式。我在重命名所有内容时告诉你。 很抱歉给您带来不便。非常感谢,非常感谢! 我正在通过按卡片添加新意图。您将获得一个完整的功能项目来学习。我会发给你一个下载链接。再给我一点时间。 当然!谢谢楼主!

以上是关于获取列表视图的arraylist的原始位置的主要内容,如果未能解决你的问题,请参考以下文章

ArrayList 适配器在列表视图中获取错误数据

从对象的 ArrayList 中获取字符串以用于自动完成文本视图

在列表视图中突出显示特定位置

获取列表视图中的图像视图位置

拖放到列表视图上,如何获取放置的项目位置

BaseAdapter 未更新列表视图中的数据