MarshallAsch/veil-droid

View on GitHub
app/src/main/java/ca/marshallasch/veil/tagList/TagListAdapter.java

Summary

Maintainability
A
1 hr
Test Coverage
package ca.marshallasch.veil.tagList;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.TextView;

import java.util.ArrayList;

import ca.marshallasch.veil.R;

/**
 * This class is the the adapter for the list of tags
 *
 * This was built based off of:
 * https://stackoverflow.com/questions/38417984/android-spinner-dropdown-checkbox/38418249#38418249
 * @author Marshall Asch
 * @version 1.0
 * @since 2018-07-24
 */
public class TagListAdapter extends ArrayAdapter<ListState>
{
    private final Context context;
    private final ArrayList<ListState> tagList;
    private boolean isFromView = false;

    /**
     * This class will hold the view view for the cell.
     */
    private class ViewHolder {
        private TextView textView;
        private CheckBox checkBox;
    }

    /**
     * Constructor with the default list of tags.
     * @param context the activities context
     */
    public TagListAdapter(@NonNull Context context)
    {
        super(context, 0);
        this.context = context;

        final String[] tagOptions = context.getResources().getStringArray(R.array.tag_list);

        tagList = new ArrayList<>();

        for (String tagOption : tagOptions) {
            tagList.add(new ListState(tagOption, false));
        }

        addAll(tagList);
    }

    @Override
    public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent)
    {
        return getCustomView(position, convertView, parent);
    }

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent)
    {
        return getCustomView(position, convertView, parent);
    }

    /**
     * This will create the view to be used for each cell. It is called by both
     * {@link #getView(int, View, ViewGroup)} and {@link #getDropDownView(int, View, ViewGroup)}
     *
     * @param position the position in the list that the view is needed for
     * @param convertView the possible old view to reuse
     * @param parent the view group
     * @return the view to display.
     */
    private View getCustomView(int position, @Nullable View convertView, @NonNull ViewGroup parent)
    {
        ListState data = tagList.get(position);

        ViewHolder holder;
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(R.layout.tag_list_item, parent, false);
            holder = new ViewHolder();
            holder.textView = convertView.findViewById(R.id.tag_name);
            holder.checkBox = convertView.findViewById(R.id.tag_selected);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.textView.setText(data.getTitle());
        isFromView  = true;
        holder.checkBox.setChecked(data.isChecked());
        isFromView = false;

        // hide the checkbox if it is the first option in the list (the title)
        if ((position == 0)) {
            holder.checkBox.setVisibility(View.INVISIBLE);
        } else {
            holder.checkBox.setVisibility(View.VISIBLE);
        }

        // set the tag so so that the click changed listener can know what position in the list its for
        holder.checkBox.setTag(position);

        // handle the event when the checkbox is checked / unchecked
        holder.checkBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
            int getPosition = (Integer) buttonView.getTag();

            if (!isFromView) {
                tagList.get(getPosition).setChecked(isChecked);

                // update the list of selected tags
                tagList.get(0).setTitle(getTagsTitle());
                notifyDataSetChanged();
            }
        });
        return convertView;
    }

    /**
     * Get a list of all the currently selected tags
     * @return an ArrayList of tags
     */
    public ArrayList<String> getSelectedTags() {

        ArrayList<String> tags = new ArrayList<>();

        // check which of the tags are selected
        for (ListState item: tagList) {
            if (item.isChecked()) {
                tags.add(item.getTitle());
            }
        }

        return tags;
    }

    /**
     * This function will generate a string list of the selected tags to be used as the first line
     * of the spinner to show all the selected items at a glance.
     * @return string of selected tags or prompt string
     */
    private String getTagsTitle() {

        StringBuilder tags = new StringBuilder();

        // check which of the tags are selected
        for (ListState item: tagList) {
            if (item.isChecked()) {
                tags.append(item.getTitle()).append(": ");
            }
        }

        if (tags.length() == 0) {
            tags = new StringBuilder(context.getString(R.string.tags_hint));
        }

        return tags.toString();
    }
}