删除ArrayList< String>长按时的项目 [英] Strikethrough an ArrayList<String> item when long pressed

查看:46
本文介绍了删除ArrayList< String>长按时的项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试制作一个简单的待办事项清单,您可以在其中长按一个项目以将其标记为完成",在这种情况下,该项目将显示为灰色并删除.

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.

我首先在删除线中工作,并在此处找到了一些示例代码创建删除线在Android中输入文字?.但是问题是setPaintFlags()方法似乎只能在TextView上使用,而我列表中的项目是String.我无法将字符串转换为TextView,但我在这里找到了解决方法,但显然不建议这样做:

I'm working on the strikethrough first and found some sample code here creating a strikethrough text in Android? . However the problem is that the setPaintFlags() method only seems to work on TextView whereas the items on my list are String. I can't cast a String to a TextView, and I found a workaround here but apparently it's highly discouraged to do it: Cast String to TextView . Also I looked up SpannableString but it doesn't seem to work for strings of varying length.

所以我回到了第一方-完全有可能实现我正在尝试做的事情吗?还是我必须以其他方式存储列表项?

So I'm back at square one - is it at all possible to implement what I'm trying to do? Or will I have to store my list items differently instead?

相关代码:

public class MainActivity extends ActionBarActivity {
    private ArrayList<String> items;
    private ArrayAdapter<String> itemsAdapter;
    private ListView lvItems;

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

        //Setting what the ListView will consist of
        lvItems = (ListView) findViewById(R.id.lvItems);

        readItems();
        itemsAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, items);
        lvItems.setAdapter(itemsAdapter);
        // Set up remove listener method call
        setupListViewListener();
    }

    //Attaches a long click listener to the listview
     private void setupListViewListener() {
        lvItems.setOnItemLongClickListener(
                new AdapterView.OnItemLongClickListener() {
                    @Override
                    public boolean onItemLongClick(AdapterView<?> adapter,
                                                   View item, int pos, long id) {


                        // Trying to make the onLongClick strikethrough the text 

                        String clickedItem = items.get(pos);
                        //What do I do here??

                        // Refresh the adapter
                        itemsAdapter.notifyDataSetChanged();
                        writeItems();
                        // Return true consumes the long click event (marks it handled)
                        return true;
                    }

                });
    }

推荐答案

让我们退后一步,考虑一下您的应用.您想向用户显示作业列表.每个作业都有说明.每个工作都有两个可能的状态:完成"或未完成".

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'

class Job
{
    private String    mDescription;
    private boolean   mDone;

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

这样,您的ArrayList'items'成为 ArrayList<作业> .一项工作是否完成将与描述一起存储.这很重要,因为您希望通过更改UI元素的外观向用户显示作业的当前状态,但是您还需要在数据级别上跟踪作业的状态.

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.

UI元素- TextView -将配置为向用户显示有关作业的信息.描述就是其中的一项信息. TextView 会将其存储为 String .另一条信息是状态(完成/未完成). TextView 将(在您的应用中)通过设置删除线标记并更改其颜色来存储它.

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.

由于性能原因, ListView 使用的元素少于数据列表('items')包含的元素,因此必须编写一个自定义适配器.为了简洁起见,我将代码保持得非常简单,但是值得花时间阅读View Holder模式:

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:

让我们使用布局文件"mytextviewlayout.xml"作为列表行:

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:orientation="vertical"
          android:layout_width="match_parent"
          android:layout_height="match_parent">

    <TextView
    android: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:

编辑从ArrayAdapter更改为BaseAdapter并添加了视图持有者(请参见评论):

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

public class MyAdapter extends BaseAdapter
{
private ArrayList<Job>         mDatalist;
private int                    mLayoutID;
private Activity               mCtx;

private MyAdapter(){} // the adapter won't work with the standard constructor

public MyAdapter(Activity context, int resource, ArrayList<Job> objects)
{
    super();
    mLayoutID = resource;
    mDatalist = objects;
    mCtx = context;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View rowView = convertView;

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

        ViewHolder viewHolder = new ViewHolder();
        viewHolder.tvDescription = (TextView) rowView.findViewById(R.id.textView);

        rowView.setTag(viewHolder); 
    }

    ViewHolder vholder = (ViewHolder) rowView.getTag();

    TextView tvJob = vholder.tvDescription;
    Job myJob = 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;
}


@Override
public int getCount()
{
    return mDatalist.size();
}

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

@Override
public long getItemId(int position)
{
    return position;
}

static class ViewHolder
{
    public TextView tvDescription;
}

}

由于更改了适配器,

在MainActivity中,您必须声明"items"和"itemsAdapter",如下所示:

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

private ArrayList<Job> items;
private MyAdapter itemsAdapter;

...并在您的'onCreate()'方法中输入:

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

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

别忘了更改'readItems()'和'writeItems()'方法,因为'items'现在是 ArrayList<作业> .

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

然后,最后是'onItemLongClick()'方法:

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

编辑,使用"parent.getItemAtPosition()"代替"items.get()",请参见注释

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

@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id)
{
     // items.get(position).setDone(true);

     Object o = parent.getItemAtPosition(position);

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

     itemsAdapter.notifyDataSetChanged(); 
     writeItems();
     return true;
 }

这篇关于删除ArrayList&lt; String&gt;长按时的项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆