Search code examples
androidexpandablerecyclerview

How to add an expandableView in a RecyclerView?


How to add an expandableView in a RecyclerView? I have a problem in implementing an expandable view in the following code. In the picture, I have fetched data from a json. How to implement the expand and collapse in a RecyclerView? I have been stuck in this code for a long time.

    public class MainActivity extends AppCompatActivity {

            private String url = "http://mantras.happylife.in/mantras_api";

            private RecyclerView mList;

            private LinearLayoutManager linearLayoutManager;
            private DividerItemDecoration dividerItemDecoration;
            private List<Mantras> mantraList;
            private RecyclerView.Adapter adapter;

            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);

                mList = findViewById(R.id.main_list);

                mantraList = new ArrayList<>();
                adapter = new MantraAdapter(getApplicationContext(),mantraList);



                linearLayoutManager = new LinearLayoutManager(this);
                linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
                dividerItemDecoration = new DividerItemDecoration(mList.getContext(), linearLayoutManager.getOrientation());

                mList.setHasFixedSize(true);
                mList.setLayoutManager(linearLayoutManager);
                mList.addItemDecoration(dividerItemDecoration);
                mList.setAdapter(adapter);

                mList.addOnItemTouchListener(
                        new RecyclerItemClickListener(this, mList ,new RecyclerItemClickListener.OnItemClickListener() {
                            @Override public void onItemClick(View view, int position) {
                                ViewGroup vg = (ViewGroup) view;
                                TextView ti = (TextView) vg.findViewById(R.id.title);
                                TextView de = (TextView) vg.findViewById(R.id.desc);

                                String selected = ti.getText().toString() + de.getText().toString();
                                Intent intent = new Intent(Intent.ACTION_SEND);
                                intent.setType("text/plain");
                                intent.putExtra(Intent.EXTRA_TEXT, selected);
                                startActivity(Intent.createChooser(intent, "Share via"));
                            }

                        })
                );


                getData();
            }

            @Override
            public boolean onCreateOptionsMenu(Menu menu) {
                getMenuInflater().inflate(R.menu.menus,menu);
                return super.onCreateOptionsMenu(menu);
            }

            @Override
            public boolean onOptionsItemSelected(MenuItem item) {

                int id = item.getItemId();
                if (id==R.id.sync_data)
                {
                    final ProgressDialog progressDialog = new ProgressDialog(this);
                    progressDialog.setMessage("Loading...");
                    progressDialog.show();
                    adapter.notifyDataSetChanged();
                    progressDialog.dismiss();

                    if (isNetworkAvailable()) {
                        Toast.makeText(this, "sync", Toast.LENGTH_SHORT).show();
                        Toast.makeText(this, "woohoo!", Toast.LENGTH_SHORT).show();
                    } else {
                        Toast.makeText(this, "no internet connection..", Toast.LENGTH_SHORT).show();
                    }

                }
                return super.onOptionsItemSelected(item);
            }

            private boolean isNetworkAvailable() {
                ConnectivityManager connectivityManager
                        = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
                return activeNetworkInfo != null && activeNetworkInfo.isConnected();
            }

            private void getData() {
                final ProgressDialog progressDialog = new ProgressDialog(this);
                progressDialog.setMessage("Loading...");
                progressDialog.show();

                JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(url, new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {
                        for (int i = 0; i < response.length(); i++) {
                            try {
                                JSONObject jsonObject = response.getJSONObject(i);

                                Mantras mantra = new Mantras();

                                String lineSep = System.getProperty("line.separator");

                                mantra.setTitle(jsonObject.getString("title"));
                                mantra.setDesc(jsonObject.getString("desc"));

                                mantra.desc= mantra.desc.replace("<br />", lineSep);
                                mantra.desc= mantra.desc.replace("<p>", lineSep);
                                mantra.desc= mantra.desc.replace("</p>", lineSep);
                                mantra.desc= mantra.desc.replace("<li>", lineSep);
                                mantra.desc= mantra.desc.replace("</li>", lineSep);
                                mantra.desc= mantra.desc.replace("<ol>", lineSep);
                                mantra.desc= mantra.desc.replace("</ol>", lineSep);
                                mantra.desc= mantra.desc.replace("<ul>", lineSep);
                                mantra.desc= mantra.desc.replace("</ul>", lineSep);




                                mantraList.add(mantra);
                            } catch (JSONException e) {
                                e.printStackTrace();
                                progressDialog.dismiss();
                            }
                        }
                        adapter.notifyDataSetChanged();
                        progressDialog.dismiss();
                    }
                }, new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Log.e("Volley", error.toString());
                        progressDialog.dismiss();
                    }
                }) {
                    @Override
                    protected Response<JSONArray> parseNetworkResponse(NetworkResponse response) {
                        try {
                            Cache.Entry cacheEntry = HttpHeaderParser.parseCacheHeaders(response);
                            if (cacheEntry == null) {
                                cacheEntry = new Cache.Entry();
                            }
                            final long cacheHitButRefreshed = 3 * 60 * 1000; // in 3 minutes cache will be hit, but also refreshed on background
                            final long cacheExpired = 24 * 60 * 60 * 1000; // in 24 hours this cache entry expires completely
                            long now = System.currentTimeMillis();
                            final long softExpire = now + cacheHitButRefreshed;
                            final long ttl = now + cacheExpired;
                            cacheEntry.data = response.data;
                            cacheEntry.softTtl = softExpire;
                            cacheEntry.ttl = ttl;
                            String headerValue;
                            headerValue = response.headers.get("Date");
                            if (headerValue != null) {
                                cacheEntry.serverDate = HttpHeaderParser.parseDateAsEpoch(headerValue);
                            }
                            headerValue = response.headers.get("Last-Modified");
                            if (headerValue != null) {
                                cacheEntry.lastModified = HttpHeaderParser.parseDateAsEpoch(headerValue);
                            }
                            cacheEntry.responseHeaders = response.headers;
                            final String jsonString = new String(response.data,
                                    HttpHeaderParser.parseCharset(response.headers));
                            return Response.success(new JSONArray(jsonString), cacheEntry);
                        } catch (UnsupportedEncodingException | JSONException e) {
                            return Response.error(new ParseError(e));
                        }
                    }

                    @Override
                    protected void deliverResponse(JSONArray response) {
                        super.deliverResponse(response);
                    }

                    @Override
                    public void deliverError(VolleyError error) {
                        super.deliverError(error);
                    }

                    @Override
                    protected VolleyError parseNetworkError(VolleyError volleyError) {
                        return super.parseNetworkError(volleyError);
                    }
                };
                RequestQueue requestQueue = Volley.newRequestQueue(this);
                requestQueue.add(jsonArrayRequest);
            }
        }

![](https://i.sstatic.net/0LCB2.jpg)

Below is the `Mantra Adapter`:

   package happy.life.mantras;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.List;




    public class MantraAdapter extends RecyclerView.Adapter<MantraAdapter.ViewHolder>{

    private Context context;
    private List<Mantras> list;
    boolean isPlay = false;


    public MantraAdapter(Context context, List<Mantras> list) {
        this.context = context;
        this.list = list;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(context).inflate(R.layout.single_item, parent, false);

        return new ViewHolder(v);
    }


    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
        Mantras movie = list.get(position);

        holder.textTitle.setText(movie.getTitle());
        holder.textDesc.setText(String.valueOf(movie.getDesc()));

        holder.textTitle.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(isPlay){
                    holder.textDesc.setVisibility(View.GONE);
                }else{
                    holder.textDesc.setVisibility(View.VISIBLE);
                }

                isPlay = !isPlay;
            }
        });

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




    public class ViewHolder extends RecyclerView.ViewHolder {
        public TextView textTitle, textDesc;

        public ViewHolder(View itemView) {
            super(itemView);

            textTitle = itemView.findViewById(R.id.title);
            textDesc = itemView.findViewById(R.id.desc);
        }
    }



}

Solution

  • Globally Declare public boolean isPlay = false;

    And Follow below code :

     @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Mantras movie = list.get(position);
    
        holder.textTitle.setText(movie.getTitle());
        holder.textDesc.setText(String.valueOf(movie.getDesc()));
    
    holder.textTitle.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(isPlay){
                    holder.textDesc.setVisibility(View.GONE);
                }else{
                    holder.textDesc.setVisibility(View.VISIBLE);
                }
    
                isPlay = !isPlay;
            }
        });
    
    }