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

查看:24
本文介绍了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 中的最后一项.所有其他项目似乎根本不会造成罢工.我的代码如下:

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 中为我的 TextViews 使用 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. getView() 在 ListView 显示时结束.OnClickListener 不应使用从 getView() 获取的数据.
  3. OnClickListener 应该能够并且需要从数据列表中获取数据.最简单的方法可能是:getView() 中的 View.setTag(position),OnClickListener() 中的 View.getTag()".
  4. 不要只修改视图.更改数据,先列出数据.然后调用notifyDataSetChanged().如果UI只有很小的变化,可以直接做,但应该和调用notifyDataSetChanged()一样.

希望有所帮助!

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

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