Skip to content Skip to sidebar Skip to footer

Strikethrough An Arraylist Item When Long Pressed

I'm trying to make a simple to-do list where you would long-press an item to mark it as 'done', in which case it will be greyed out and strikethrough. I'm working on the strikethr

Solution 1:

Let's take a step back and consider your app. You want to show a list of jobs to the user. Each job has a description. And each job has two possible states: 'done' or 'not done'.

So I would like to introduce a class 'Job'

classJob
{
    privateString    mDescription;
    privateboolean   mDone;

    publicJob(String description)
    {
         this.mDescription = description;
         this.mDone = false;
    }
    // ... generate the usual getters and setters here ;-)// especially:publicbooleanisDone()
    {
         return mIsDone;
    }
}

This way your ArrayList 'items' becomes be a ArrayList< Job >. Wether a job is done or not will be stored together with its description. This is important because you want to show the current state of the job to the user by changing the look of the UI element, but you need to keep track of the job's state on the data level as well.

The UI element - the TextView - will be configured to present information about the job to the user. One piece of information is the description. The TextView will store this as a String. The other piece of information is the state (done/ not done). The TextView will (in your app) store this by setting the strike-through flag and changing its color.

Because for performance reasons a ListView uses less elements than the data list ('items') contains, you have to write a custom adapter. For brevity's sake, I'm keeping the code very simple, but it's worth the time to read up on the View Holder pattern:

Let's use a layout file 'mytextviewlayout.xml' for the list rows:

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:textAppearance="?android:attr/textAppearanceMedium"android:text="Medium Text"android:id="@+id/textView"/></LinearLayout>

Now the code for the adapter looks like this:

EDIT changed from ArrayAdapter to BaseAdapter and added a view holder (see comments):

publicclassMyAdapterextendsBaseAdapter
{
private ArrayList<Job>         mDatalist;
privateint                    mLayoutID;
private Activity               mCtx;

privateMyAdapter(){} // the adapter won't work with the standard constructorpublicMyAdapter(Activity context, int resource, ArrayList<Job> objects)
{
    super();
    mLayoutID = resource;
    mDatalist = objects;
    mCtx = context;
}

@Overridepublic View getView(int position, View convertView, ViewGroup parent) {
    ViewrowView= convertView;

    if (rowView == null) {
        LayoutInflaterinflater= mCtx.getLayoutInflater();
        rowView = inflater.inflate(mLayoutID, null);

        ViewHolderviewHolder=newViewHolder();
        viewHolder.tvDescription = (TextView) rowView.findViewById(R.id.textView);

        rowView.setTag(viewHolder); 
    }

    ViewHoldervholder= (ViewHolder) rowView.getTag();

    TextViewtvJob= vholder.tvDescription;
    JobmyJob= mDatalist.get(position);

    tvJob.setText(myJob.getJobDescription());
    if (myJob.isDone())
    {
        // apply changes to TextView
        tvJob.setPaintFlags(tvJob.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
        tvJob.setTextColor(Color.GRAY);
    }
    else
    {
        // show TextView as usual
        tvJob.setPaintFlags(tvJob.getPaintFlags() &    (~Paint.STRIKE_THRU_TEXT_FLAG));
        tvJob.setTextColor(Color.BLACK); // or whatever is needed...
    }

    return rowView;
}


@OverridepublicintgetCount()
{
    return mDatalist.size();
}

@Overridepublic Object getItem(int position)
{
    return mDatalist.get(position);
}

@OverridepubliclonggetItemId(int position)
{
    return position;
}

staticclassViewHolder
{
    public TextView tvDescription;
}

}

Due to the changed adapter,

in the MainActivity, you have to declare 'items' and 'itemsAdapter' as follows:

privateArrayList<Job> items;
privateMyAdapter itemsAdapter;

...and in your 'onCreate()' method, you write:

itemsAdapter = new MyAdapter<String>(this, R.layout.mytextviewlayout, items);

Don't forget to change the 'readItems()' and 'writeItems()' methods because 'items' now is a ArrayList< Job >.

Then, finally, the 'onItemLongClick()' method:

EDIT use 'parent.getItemAtPosition()' instead of 'items.get()', see comments

@OverridepublicbooleanonItemLongClick(AdapterView<?> parent, View view, int position, long id)
{
     // items.get(position).setDone(true);Objecto= parent.getItemAtPosition(position);

     if (o instanceof Job)
     {
         ((Job) o).setDone(true);
     }
     // and now indeed the data set has changed :)

     itemsAdapter.notifyDataSetChanged(); 
     writeItems();
     returntrue;
 }

Post a Comment for "Strikethrough An Arraylist Item When Long Pressed"