RecyclerView - Get the selected position and pass the position to another activity where the same list will appear with that specific item selected

nideba :

I have declared a ViewModel.class for the RecyclerView an Adapter and I have parsed to the MainActivity and to another Activity so I have the same adapter for both activities.

I can show the parsed data in both activities but the problem it is I cannot take the data of the selected item to MainActivity and then to set to that btnSearch for a click so then I can share between activities the data from the selected item.

Every time when the app is open the first item is selected. What I am trying to achieve is.

  1. Get the item position to the MainActivity so when I click for a button search the data of the selectedItem will going to intent.putExtra and then get the data at another Activity.
  2. If I click the second item and go to another Activity the same item will be selected.

Here is what I have tried so far.

The SearchEngineAdapter.class

public class SearchEngineAdapter extends RecyclerView.Adapter<SearchEngineAdapter.ViewHolder> {
    private int selectedItem = 0;
    private static RecyclerViewClickListener itemListener;

    private Context context;
    ArrayList<SearchEngine> arrayList = new ArrayList<>();

    public SearchEngineAdapter(Context context, ArrayList<SearchEngine> arrayList, int selectedItem) {
        this.context = context;
        this.arrayList = arrayList;
        this.selectedItem = selectedItem;
    }

    @Override
    public void onBindViewHolder(@NonNull final ViewHolder holder, final int i) {
        holder.tvIcon.setImageResource(arrayList.get(i).getIcon());
        holder.tvId.setText(arrayList.get(i).getId());
        holder.tvSearchUrl.setText(arrayList.get(i).getUrl());
        final String url = holder.tvSearchUrl.getText().toString();

        SharedPreferences sp = context.getSharedPreferences("SavedSelected", Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.putInt("selected", selectedItem);
        editor.apply();

        sp = context.getSharedPreferences("SavedSelected", Context.MODE_PRIVATE);
        int myIntValue = sp.getInt("selected", -1);
        Log.d("Selected", "SharedPreferences" + myIntValue);

        if (selectedItem == i) {
            holder.tvIcon.setBackgroundColor(Color.parseColor("#30000000"));
            Intent intent = new Intent("search_engines");
            intent.putExtra("url", url);
            intent.putExtra("selected", selectedItem);
            LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
        } else {
            holder.tvIcon.setBackgroundColor(Color.parseColor("#00000000"));
        }

        holder.tvIcon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent("search_engines");
                intent.putExtra("url", url);
                int PreviousSelectedItem = selectedItem;
                selectedItem = i;
                intent.putExtra("selected", selectedItem);
                holder.tvIcon.setBackgroundColor(Color.parseColor("#30000000"));
                notifyItemChanged(PreviousSelectedItem);
                notifyDataSetChanged();
            }
        });
    }

    // ... Other necessary functions.
}

Now the MainActivity.class

RecyclerView paramRecyclerView;
SearchEngineAdapter sEngineAdapter;

paramRecyclerView = findViewById(R.id.lvEngines);
paramRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
paramRecyclerView.setHasFixedSize(true);
Intent intent = getIntent();
int intValue = intent.getIntExtra("selected", 0);
sEngineAdapter = new SearchEngineAdapter(context, arrayList, intValue);
paramRecyclerView.setAdapter(sEngineAdapter);

// Calling network APIs to populate the arrayList.

The onResume function of the MainActivity looks like the following.

protected void onResume() {
    super.onResume();
    searchPlugin.setText("");
    getChangeColor();
}

This is the click handler defined in MainActivity which send me to another Activity.

btnSearch.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        String newEntry = searchPlugin.getText().toString();
        AddHistory(newEntry);
        getFragmentRefreshListener().onRefresh();
        Intent intent = new Intent(MainActivity.this, ActivitySearchEngine.class);
        intent.putExtra("url", url );
        intent.putExtra("name", newEntry);
        intent.putExtra("selected", selectedItem2);
        startActivity(intent);
    }
});

And the other activity which is ActivitySearchEngine.class

public class ActivitySearchEngine extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {

    public String selectedName;
    public int selectedID;
    public String selectedSearchUrl;
    RecyclerView mListView;
    RecyclerView paramRecyclerView;
    SearchEngineAdapter sEngineAdapter;

    ArrayList<SearchEngine> arrayList = new ArrayList<>();
    final Context context = this;
    int selectedItem;

    @SuppressLint("SetJavaScriptEnabled")
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search_result);

        // Variables initialization

        // Setting up adapter
        paramRecyclerView.setAdapter(sEngineAdapter);
        sEngineAdapter.notifyDataSetChanged();

        // Calling network APIs to populate the arrayList here

        Intent receivedIntent = getIntent();
        selectedName = receivedIntent.getStringExtra("name");
        selectedID = receivedIntent.getIntExtra("id", 1); //NOTE: -1 is just the default value
        selectedSearchUrl = receivedIntent.getStringExtra("url");

        // Loading the url in a WebView for searching
    }
}

I could share the selected item position between these two activities. However, I am not sure how to achieve the behavior of the item is being selected in the RecyclerView of the second activity as well. If I select another item in the RecyclerView of the second activity, the change should be reflected in the first (i.e. MainActivity) as well when I get back to it.

Any help would be appreciated.

Reaz Murshed :

There was a lot of changes in the question and hence the last update of this answer below is the final version.

As far as I could understand about the problem, I can see you are very close to the solution if I had understood correctly. The SearchEngineAdapter already has a selectedItem variable in it which can be used for highlighting the item selected in ActivitySearchEngine as well. You just have to modify the adapter a little bit like the following. I am rewriting the adapter here.

public class SearchEngineAdapter extends RecyclerView.Adapter<SearchEngineAdapter.ViewHolder> {
    private int selectedItem = 0;
    private static RecyclerViewClickListener itemListener;

    private Context context;
    ArrayList<SearchEngine> arrayList = new ArrayList<>();

    // Added another argument to be passed in the constructor
    public SearchEngineAdapter(Context context, ArrayList<SearchEngine> arrayList, int selectedItem) {
        this.context = context;
        this.arrayList = arrayList;
        this.selectedItem = selectedItem;
    }

    @NonNull
    @Override
    public SearchEngineAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(context).inflate(R.layout.s_engine_item, viewGroup, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull final ViewHolder holder, final int i) {
        if (selectedItem == i) {
            holder.tvIcon.setBackgroundColor(Color.parseColor("#30000000"));
        } else {
            holder.tvIcon.setBackgroundColor(Color.parseColor("#00000000"));
        }

        holder.tvIcon.setImageResource(arrayList.get(i).getIcon());
        holder.tvId.setText(arrayList.get(i).getId());
        holder.tvSearchUrl.setText(arrayList.get(i).getUrl());

        holder.tvIcon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int PreviousSelectedItem = selectedItem;
                selectedItem = i;
                holder.tvIcon.setBackgroundColor(Color.parseColor("#30000000"));
                notifyItemChanged(PreviousSelectedItem);
                notifyDataSetChanged();
            }
        });
    }

    @Override
    public int getItemCount() {
        return arrayList.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder{
        TextView tvId, tvSearchUrl;
        ImageView tvIcon;
        public ViewHolder(@NonNull View itemView) {
            super(itemView);

            tvId = itemView.findViewById(R.id.ivEngineText);
            tvIcon = itemView.findViewById(R.id.ivEngine);
            tvSearchUrl = itemView.findViewById(R.id.ivSearchUrl);
        }
    }
}

Check that, I just have modified the constructor of your adapter, taking another extra variable which is selectedItem. Just pass the selected item position when you are initializing the adapter in both activities. In the default case, you can pass -1, I think you get the idea.

You have passed the selected item position to the ActivitySearchEngine as well. Which can be used for initializing for the desired behavior. Hope that helps!

Update 1:

I would like to suggest you put the following code to your onResume function in the ActivitySearchEngine class. You might consider removing the lines from the onCreate function of your code as well.

@Override
public void onResume() {
    super.onResume();

    Intent receivedIntent = getIntent();
    selectedName = receivedIntent.getStringExtra("name");
    selectedID = receivedIntent.getIntExtra("id", 1); // NOTE: -1 is just the default value
    selectedSearchUrl = receivedIntent.getStringExtra("url");

    sEngineAdapter = new SearchEngineAdapter(context, arrayList, selectedID);
    paramRecyclerView.setAdapter(sEngineAdapter);
}

Update 2:

The RecyclerView in your MainActivity is getting reloaded as you are setting the adapter again to the RecyclerView in the onResume function. Moreover, you are trying to get data from intent which is not available here I think because you have not set any data to be sent to the MainActivity when you return back from the ActivitySearchEngine. Hence, the RecyclerView is reloading again with a fresh set of data.

You might remove the code associated with your RecyclerView from the onResume function of the MainActivity to remove this complication as I think this is not necessary. So the updated onResume function will look like the following.

protected void onResume() {
    super.onResume();
    searchPlugin.setText("");
    getChangeColor();
}

Update 3:

Take a public static variable in your MainAcitivity and declare it as a global variable like the following.

// Setting 0 as you wanted to put the first item at the first time
// If you do not want that, then initialize with -1
public static int selectedItem = 0; 

Now inside your onCreate function, remove the lines for getting the intent.

paramRecyclerView = findViewById(R.id.lvEngines);
paramRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
paramRecyclerView.setHasFixedSize(true);

// Remove the following
// Intent intent = getIntent();
// int intValue = intent.getIntExtra("selected", 0);

// Move the adapter setup to the onResume
// sEngineAdapter = new SearchEngineAdapter(context, arrayList, selectedItem);
// paramRecyclerView.setAdapter(sEngineAdapter);

// Calling network APIs to populate the arrayList.

Modify the onResume function in the MainActivity to set up the adapter there.

protected void onResume() {
    super.onResume();
    searchPlugin.setText("");
    getChangeColor();

    // Set the adapter here 
    sEngineAdapter = new SearchEngineAdapter(context, arrayList, selectedItem);
    paramRecyclerView.setAdapter(sEngineAdapter);
}

Modify the onClickListener in your adapter like the following. Just add a new line there.

holder.tvIcon.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent("search_engines");
        intent.putExtra("url", url);
        int PreviousSelectedItem = selectedItem;
        selectedItem = i;

        // Set the static value in the MainActivity 
        // This can be accessed from all other classes
        MainActivity.selectedItem = i;

        intent.putExtra("selected", selectedItem);
        holder.tvIcon.setBackgroundColor(Color.parseColor("#30000000"));
        notifyItemChanged(PreviousSelectedItem);
        notifyDataSetChanged();
    }
});

Hope that helps!

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=152595&siteId=1