Spannable String仅适用于ListView中的最后一个项目 [英] Spannable String only working for last Item in ListView

查看:71
本文介绍了Spannable String仅适用于ListView中的最后一个项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我现在可以在列表视图中删除单词,但只能从下往上进行操作,之后只能取消删除底部的内容.代码如下.

I'm now able to strike words in the listview but only able to do it from the bottom up and can only unstrike the bottom item afterwards. The code is below.

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    final SubTask subTask = getItem(position);

    if(convertView == null){
        convertView = LayoutInflater.from(getContext()).inflate(R.layout.subtask_adapter_list, parent, false);
    }

    final TextView tasksTitle = (TextView)convertView.findViewById(R.id.tasksName);
    tasksTitle.setTypeface(typeface);
    completed = (CheckBox)convertView.findViewById(R.id.completed);
    changeColor();

    tasksTitle.setText(subTask.getSubTask());

    completed.setChecked(subTask.isCompleted());

    toggleLineThrough(tasksTitle, tasksTitle.getText().toString(), subTask.getSubTask(), completed.isChecked());

    completed.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if(completed.isChecked()){
                subTask.setCompleted(true);
                subTask.save();
                toggleLineThrough(tasksTitle, tasksTitle.getText().toString(), subTask.getSubTask(), completed.isChecked());
            } else {
                subTask.setCompleted(false);
                subTask.save();
                toggleLineThrough(tasksTitle, tasksTitle.getText().toString(), subTask.getSubTask(), completed.isChecked());
            }
        }
    });

    return convertView;
}

private void toggleLineThrough(TextView tasksTitle, String title, String oldTitle, boolean completed){
    SpannableString styledString = new SpannableString(title);
    if(completed == true){
        styledString.setSpan(new StrikethroughSpan(), 0, title.length(), 0);
        tasksTitle.setText(styledString);
    } else {
        tasksTitle.setText(oldTitle);
    }
}

如果要满足TextView的标准,我会尝试使它跨过罢工.从逻辑上讲,它有效,但仅适用于ListView中的最后一个Item.所有其他物品似乎根本不会造成罢工.我的代码如下:

I'm trying to have the strike going across a TextView if it's criteria is met. Logically it works, but only for the last Item in the ListView. All other Items don't seem to create the strike at all. My code is below:

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

    if(convertView == null){
        convertView = LayoutInflater.from(getContext()).inflate(R.layout.subtask_adapter_list, parent, false);
    }

    tasksTitle = (TextView)convertView.findViewById(R.id.tasksName);
    tasksTitle.setTypeface(typeface);
    completed = (CheckBox)convertView.findViewById(R.id.completed);
    changeColor();

    tasksTitle.setText(subTask.getSubTask());

    toggleLineThrough(subTask.getSubTask());

    completed.setChecked(subTask.isCompleted());

    completed.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if(completed.isChecked()){
                subTask.setCompleted(true);
                subTask.save();
                toggleLineThrough(subTask.getSubTask());
            } else {
                subTask.setCompleted(false);
                subTask.save();
                toggleLineThrough(subTask.getSubTask());
            }
        }
    });

    return convertView;
}

private void toggleLineThrough(String text){
    SpannableString styledString = new SpannableString(text);
    if(completed.isChecked()){
        styledString.setSpan(new StrikethroughSpan(), 0, text.length(), 0);
        tasksTitle.setText(styledString);
    } else {
        tasksTitle.setText(text);
    }
}

我似乎无法为他们全部罢工.我也尝试过使用具有相同结果的Paint Flags方法(甚至完全隐藏了我的TextView).我们非常感谢在ListView中为我的TextView使用Spannable String的任何帮助.

I just can't seem to get the strike to work for them all. I've tried also using the Paint Flags way with the same result (even hiding my TextView altogether). Any help using Spannable String for my TextViews in the ListView would be really appreciated.

推荐答案

@SmiffyKmc,我正在尝试使用以下内容回答其他类似的问题,因此某些评论可能与您的问题无关.

@SmiffyKmc, I am trying to use the following to answer other similar questions, so some comments may not related to your problem.

在这里制作了完整的示例:

Have made a completed sample here:

在strings.xml中:

in strings.xml:

    <string-array name="list_items_sample">
    <item>One</item>
    <item>Two</item>
    <item>Three</item>
    <item>Four</item>
    <item>Five</item>
    <item>Six</item>
    <item>Seven</item>
    <item>Eight</item>
    <item>Nine</item>
    <item>Ten</item>
    <item>Eleven</item>
    <item>Twelve</item>
    <item>Thirteen</item>
    <item>Fourteen</item>
    <item>Fifteen</item>
    <item>Sixteen</item>
    <item>Seventeen</item>
    <item>Eighteen</item>
    <item>Nineteen</item>
    <item>Twenty</item>
</string-array>

activity_main.xml:

activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}" >

<ListView
    android:id="@+id/listView1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="7dp" >

</ListView>

custom_list_items.xml:

custom_list_items.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/RelativeLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingBottom="20dp"
android:paddingTop="20dp" >

<CheckBox
    android:id="@+id/cb"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentEnd="true"
    android:layout_alignParentRight="true"
    android:focusable="false" />

<TextView
    android:id="@+id/tvId"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignBaseline="@+id/cb"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_alignParentTop="true"
    android:layout_marginBottom="5dp"
    android:layout_marginTop="5dp"
    android:gravity="center"
    android:minWidth="70dp"
    android:textSize="25sp" />

<TextView
    android:id="@+id/tvDescription"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignBaseline="@+id/cb"
    android:layout_alignParentTop="true"
    android:layout_toEndOf="@id/tvId"
    android:layout_toLeftOf="@+id/cb"
    android:layout_toRightOf="@id/tvId"
    android:layout_toStartOf="@id/cb" />

MainActivity.java:

MainActivity.java:

public class MainActivity extends Activity {
static final String ITEM_ID = "item_id";
static final String ITEM_NAME = "item_name";
static final String ITEM_CHECKED ="item_checked";
ListView mListView;

ArrayList<HashMap<String, Object>> mDataList = new ArrayList<>();
ArrayAdapter<HashMap<String, Object>> mArrayAdapter;

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

    mListView = (ListView) findViewById(R.id.listView1);

    String items[] = getResources().getStringArray(R.array.list_items_sample);
    mDataList.clear();
    for(int i=1; i<20; i++){
        HashMap<String, Object> newItem = new HashMap<String, Object>();
        newItem.put(ITEM_ID, String.valueOf(i));
        newItem.put(ITEM_NAME, "Sample<"+items[i-1]+">");
        newItem.put(ITEM_CHECKED, false);
        mDataList.add(newItem);
    }

    mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);

    mArrayAdapter = new ArrayAdapter<HashMap<String, Object>>(getApplicationContext(), R.layout.custom_list_items, mDataList){
        class ViewHolder{
            CheckBox cb;
            TextView tvId;
            TextView tvDescription;
        }
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            // Prepare views ready for data
            if(convertView == null){
                convertView = LayoutInflater.from(getContext()).inflate(R.layout.custom_list_items, parent, false);
                holder = new ViewHolder();
                holder.cb = (CheckBox) convertView.findViewById(R.id.cb);
                holder.tvId = (TextView) convertView.findViewById(R.id.tvId);
                holder.tvDescription = (TextView) convertView.findViewById(R.id.tvDescription);
                convertView.setTag(holder);

                holder.cb.setOnClickListener(new OnClickListener(){
                    @Override
                    public void onClick(View view) {
                        // Get view, position and DataList(position)
                        CheckBox buttonView = (CheckBox) view;
                        int pos = (int) buttonView.getTag();
                        HashMap<String, Object> selectedItem = new HashMap<String, Object>();
                        selectedItem = getItem(pos);

                        // Update DataList
                        remove(selectedItem);
                        selectedItem.remove(ITEM_CHECKED);
                        if(buttonView.isChecked()){
                            selectedItem.put(ITEM_CHECKED, true);
                            insert(selectedItem, pos);
                        }else{
                            selectedItem.put(ITEM_CHECKED, false);
                            insert(selectedItem, pos);
                        }

                        // Update all UI views by
                        notifyDataSetChanged();
                        // or Update the affected views directly
//                          View itemView = (View) buttonView.getParent();
//                          TextView tv = (TextView) itemView.findViewById(R.id.tvDescription);
//                          toggleLineThrough(tv, (String)getItem(pos).get(ITEM_NAME), buttonView.isChecked());
                    }
                });
            }else{
                holder = (ViewHolder) convertView.getTag();
            }

            // Get data from DataList
            HashMap<String, Object> currentItem = getItem(position);

            // Setup List items UI
            holder.tvId.setText((String)currentItem.get(ITEM_ID));
            holder.cb.setChecked((boolean)currentItem.get(ITEM_CHECKED));
            toggleLineThrough(holder.tvDescription, (String)currentItem.get(ITEM_NAME), (boolean)currentItem.get(ITEM_CHECKED));

            // Save position to CheckBox, so position can be retrieved when CheckBox is clicked
            holder.cb.setTag(position);

            return convertView;
        }
        private void toggleLineThrough(TextView tasksTitle, String title, boolean completed){
            SpannableString styledString = new SpannableString(title);
            if(completed == true){
                styledString.setSpan(new StrikethroughSpan(), 0, title.length(), 0);
                tasksTitle.setText(styledString);
            }else{
                tasksTitle.setText(title);
            }
        }
    };
    mListView.setAdapter(mArrayAdapter);
}
}

一些要点:

  1. 将CheckBox的状态保留为数据列表中的字段,并相应地设置UI,否则滚动后ListView将错误.
  2. 显示ListView时,
  3. getView()已经结束. OnClickListener不应使用从getView()获得的数据.
  4. OnClickListener应该并且必须从数据列表中获取数据.最简单的方法可能是:"getView()中的View.setTag(位置),OnClickListener()中的View.getTag()".
  5. 不仅只是修改视图.首先更改数据,数据列表.然后调用notifyDataSetChanged().如果对UI的更改很小,则可以直接进行更改,但应与调用notifyDataSetChanged()相同.
  1. Keep state of the CheckBox as a field in data list and setup UI accordingly, otherwise ListView will be wrong after scroll.
  2. getView() is over when the ListView is shown. OnClickListener SHOULD NOT use the data obtained from getView().
  3. OnClickListener SHOULD ABLE and NEED to get data from data list. The simplest method may be: "View.setTag(position) in getView(), View.getTag() in OnClickListener()".
  4. Don't just modified views only. Change data, data list first. Then call notifyDataSetChanged(). If there is only a small change to UI, can do it directly but should be the same as calling notifyDataSetChanged().

希望有帮助!

这篇关于Spannable String仅适用于ListView中的最后一个项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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