简体   繁体   English

ListView不显示文本,但显示数字(使用过的SimpleAdapter)

[英]ListView not displaying text but displaying number (used SimpleAdapter)

So I'm creating a to-do app and I'm a newbie at java programming and Android Studio, so I hope you can bear with me. 因此,我正在创建一个待办事项应用程序,并且是Java编程和Android Studio的新手,所以我希望您能忍受。

Here's my MainActivity containing a SimpleAdapter to display a list. 这是我的MainActivity,其中包含一个用于显示列表的SimpleAdapter。

    ListView lv;
    ArrayList<HashMap<String, String>> list;
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_listview_main_activity);
    lv=(ListView)findViewById(R.id.listingtasks);

    DBconnector db=new DBconnector(this);
    list=new ArrayList<HashMap<String,String>>();
    list=db.display();
    String[] from=new String[]{"_id","task"};
    int[] to=new int[]{R.id.id,R.id.tasknamecustom1};

    ListAdapter ad;
    ad = new SimpleAdapter(listview_main_activity.this,list, R.layout.custom,from,to);
    lv.setAdapter(ad);

The DBconnector class extends from the SQLiteOpenHelper class and contains methods that insert and display the records in the SQLiteDatabase. DBconnector类从SQLiteOpenHelper类扩展而来,并包含在SQLiteDatabase中插入并显示记录的方法。 Here's the DBconnector class: 这是DBconnector类:

public class DBconnector extends SQLiteOpenHelper {

public Cursor cr;

public DBconnector(Context context) {
    super(context, "DATABASE", null, 1);
}



@Override
public void onCreate(SQLiteDatabase db) {
    String sqlquery = "CREATE TABLE TASKTABLE(_id INTEGER PRIMARY KEY AUTOINCREMENT, task TEXT);";
    db.execSQL(sqlquery);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    String sqlqueryupgrade = "DROP TABLE IF EXISTS TASKTABLE;";
    db.execSQL(sqlqueryupgrade);
    onCreate(db);
}

Here's the display method within the DBconnector class: 这是DBconnector类中的显示方法:

 public ArrayList<HashMap<String,String>> display() {

    ArrayList<HashMap<String,String>> list = new ArrayList<HashMap<String,String>>();
    SQLiteDatabase sb = this.getReadableDatabase();
    String sql = "SELECT * FROM TASKTABLE;";
    cr = sb.rawQuery(sql, null); //takes cursor to a position before the first record
    if (cr.moveToFirst()) {
        do {
            HashMap<String,String> hm = new HashMap<String,String>();

            hm.put("_id", cr.getString(0));
            hm.put("task", cr.getString(1));
            list.add(hm);


        } while (cr.moveToNext());


    }

    return list;

}

Here's the custom.xml file: 这是custom.xml文件:

<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/textAppearanceSmall"
    android:text="Small Text"
    android:id="@+id/id" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:text="Large Text"
    android:id="@+id/tasknamecustom1" />

There are no syntactical errors. 没有语法错误。 I don't find any red underlines anywhere and the app runs on my phone. 我在任何地方都找不到红色下划线,并且该应用程序在手机上运行。 The only problem is that the listview of my main activity displays the number of the tasks properly but doesn't display the text of the task itself. 唯一的问题是我的主要活动的列表视图正确显示了任务数,但没有显示任务本身的文本。

Here's the SimpleAdapter class: 这是SimpleAdapter类:

public class SimpleAdapter extends BaseAdapter implements Filterable,      ThemedSpinnerAdapter {
private final LayoutInflater mInflater;

private int[] mTo;
private String[] mFrom;
private ViewBinder mViewBinder;

private List<? extends Map<String, ?>> mData;

private int mResource;
private int mDropDownResource;

/** Layout inflater used for {@link #getDropDownView(int, View, ViewGroup)}. */
private LayoutInflater mDropDownInflater;

private SimpleFilter mFilter;
private ArrayList<Map<String, ?>> mUnfilteredData;

/**
 * Constructor
 *
 * @param context The context where the View associated with this SimpleAdapter is running
 * @param data A List of Maps. Each entry in the List corresponds to one row in the list. The
 *        Maps contain the data for each row, and should include all the entries specified in
 *        "from"
 * @param resource Resource identifier of a view layout that defines the views for this list
 *        item. The layout file should include at least those named views defined in "to"
 * @param from A list of column names that will be added to the Map associated with each
 *        item.
 * @param to The views that should display column in the "from" parameter. These should all be
 *        TextViews. The first N views in this list are given the values of the first N columns
 *        in the from parameter.
 */
public SimpleAdapter(Context context, List<? extends Map<String, ?>> data,
        @LayoutRes int resource, String[] from, @IdRes int[] to) {
    mData = data;
    mResource = mDropDownResource = resource;
    mFrom = from;
    mTo = to;
    mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

/**
 * @see android.widget.Adapter#getCount()
 */
public int getCount() {
    return mData.size();
}

/**
 * @see android.widget.Adapter#getItem(int)
 */
public Object getItem(int position) {
    return mData.get(position);
}

/**
 * @see android.widget.Adapter#getItemId(int)
 */
public long getItemId(int position) {
    return position;
}

/**
 * @see android.widget.Adapter#getView(int, View, ViewGroup)
 */
public View getView(int position, View convertView, ViewGroup parent) {
    return createViewFromResource(mInflater, position, convertView, parent, mResource);
}

private View createViewFromResource(LayoutInflater inflater, int position, View convertView,
        ViewGroup parent, int resource) {
    View v;
    if (convertView == null) {
        v = inflater.inflate(resource, parent, false);
    } else {
        v = convertView;
    }

    bindView(position, v);

    return v;
}

/**
 * <p>Sets the layout resource to create the drop down views.</p>
 *
 * @param resource the layout resource defining the drop down views
 * @see #getDropDownView(int, android.view.View, android.view.ViewGroup)
 */
public void setDropDownViewResource(int resource) {
    mDropDownResource = resource;
}

/**
 * Sets the {@link android.content.res.Resources.Theme} against which drop-down views are
 * inflated.
 * <p>
 * By default, drop-down views are inflated against the theme of the
 * {@link Context} passed to the adapter's constructor.
 *
 * @param theme the theme against which to inflate drop-down views or
 *              {@code null} to use the theme from the adapter's context
 * @see #getDropDownView(int, View, ViewGroup)
 */
@Override
public void setDropDownViewTheme(Resources.Theme theme) {
    if (theme == null) {
        mDropDownInflater = null;
    } else if (theme == mInflater.getContext().getTheme()) {
        mDropDownInflater = mInflater;
    } else {
        final Context context = new ContextThemeWrapper(mInflater.getContext(), theme);
        mDropDownInflater = LayoutInflater.from(context);
    }
}

@Override
public Resources.Theme getDropDownViewTheme() {
    return mDropDownInflater == null ? null : mDropDownInflater.getContext().getTheme();
}

@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
    final LayoutInflater inflater = mDropDownInflater == null ? mInflater : mDropDownInflater;
    return createViewFromResource(inflater, position, convertView, parent, mDropDownResource);
}

private void bindView(int position, View view) {
    final Map dataSet = mData.get(position);
    if (dataSet == null) {
        return;
    }

    final ViewBinder binder = mViewBinder;
    final String[] from = mFrom;
    final int[] to = mTo;
    final int count = to.length;

    for (int i = 0; i < count; i++) {
        final View v = view.findViewById(to[i]);
        if (v != null) {
            final Object data = dataSet.get(from[i]);
            String text = data == null ? "" : data.toString();
            if (text == null) {
                text = "";
            }

            boolean bound = false;
            if (binder != null) {
                bound = binder.setViewValue(v, data, text);
            }

            if (!bound) {
                if (v instanceof Checkable) {
                    if (data instanceof Boolean) {
                        ((Checkable) v).setChecked((Boolean) data);
                    } else if (v instanceof TextView) {
                        // Note: keep the instanceof TextView check at the bottom of these
                        // ifs since a lot of views are TextViews (e.g. CheckBoxes).
                        setViewText((TextView) v, text);
                    } else {
                        throw new IllegalStateException(v.getClass().getName() +
                                " should be bound to a Boolean, not a " +
                                (data == null ? "<unknown type>" : data.getClass()));
                    }
                } else if (v instanceof TextView) {
                    // Note: keep the instanceof TextView check at the bottom of these
                    // ifs since a lot of views are TextViews (e.g. CheckBoxes).
                    setViewText((TextView) v, text);
                } else if (v instanceof ImageView) {
                    if (data instanceof Integer) {
                        setViewImage((ImageView) v, (Integer) data);                            
                    } else {
                        setViewImage((ImageView) v, text);
                    }
                } else {
                    throw new IllegalStateException(v.getClass().getName() + " is not a " +
                            " view that can be bounds by this SimpleAdapter");
                }
            }
        }
    }
}

/**
 * Returns the {@link ViewBinder} used to bind data to views.
 *
 * @return a ViewBinder or null if the binder does not exist
 *
 * @see #setViewBinder(android.widget.SimpleAdapter.ViewBinder)
 */
public ViewBinder getViewBinder() {
    return mViewBinder;
}

/**
 * Sets the binder used to bind data to views.
 *
 * @param viewBinder the binder used to bind data to views, can be null to
 *        remove the existing binder
 *
 * @see #getViewBinder()
 */
public void setViewBinder(ViewBinder viewBinder) {
    mViewBinder = viewBinder;
}

/**
 * Called by bindView() to set the image for an ImageView but only if
 * there is no existing ViewBinder or if the existing ViewBinder cannot
 * handle binding to an ImageView.
 *
 * This method is called instead of {@link #setViewImage(ImageView, String)}
 * if the supplied data is an int or Integer.
 *
 * @param v ImageView to receive an image
 * @param value the value retrieved from the data set
 *
 * @see #setViewImage(ImageView, String)
 */
public void setViewImage(ImageView v, int value) {
    v.setImageResource(value);
}

/**
 * Called by bindView() to set the image for an ImageView but only if
 * there is no existing ViewBinder or if the existing ViewBinder cannot
 * handle binding to an ImageView.
 *
 * By default, the value will be treated as an image resource. If the
 * value cannot be used as an image resource, the value is used as an
 * image Uri.
 *
 * This method is called instead of {@link #setViewImage(ImageView, int)}
 * if the supplied data is not an int or Integer.
 *
 * @param v ImageView to receive an image
 * @param value the value retrieved from the data set
 *
 * @see #setViewImage(ImageView, int) 
 */
public void setViewImage(ImageView v, String value) {
    try {
        v.setImageResource(Integer.parseInt(value));
    } catch (NumberFormatException nfe) {
        v.setImageURI(Uri.parse(value));
    }
}

/**
 * Called by bindView() to set the text for a TextView but only if
 * there is no existing ViewBinder or if the existing ViewBinder cannot
 * handle binding to a TextView.
 *
 * @param v TextView to receive text
 * @param text the text to be set for the TextView
 */
public void setViewText(TextView v, String text) {
    v.setText(text);
}

public Filter getFilter() {
    if (mFilter == null) {
        mFilter = new SimpleFilter();
    }
    return mFilter;
}

/**
 * This class can be used by external clients of SimpleAdapter to bind
 * values to views.
 *
 * You should use this class to bind values to views that are not
 * directly supported by SimpleAdapter or to change the way binding
 * occurs for views supported by SimpleAdapter.
 *
 * @see SimpleAdapter#setViewImage(ImageView, int)
 * @see SimpleAdapter#setViewImage(ImageView, String)
 * @see SimpleAdapter#setViewText(TextView, String)
 */
public static interface ViewBinder {
    /**
     * Binds the specified data to the specified view.
     *
     * When binding is handled by this ViewBinder, this method must return true.
     * If this method returns false, SimpleAdapter will attempts to handle
     * the binding on its own.
     *
     * @param view the view to bind the data to
     * @param data the data to bind to the view
     * @param textRepresentation a safe String representation of the supplied data:
     *        it is either the result of data.toString() or an empty String but it
     *        is never null
     *
     * @return true if the data was bound to the view, false otherwise
     */
    boolean setViewValue(View view, Object data, String textRepresentation);
}

/**
 * <p>An array filters constrains the content of the array adapter with
 * a prefix. Each item that does not start with the supplied prefix
 * is removed from the list.</p>
 */
private class SimpleFilter extends Filter {

    @Override
    protected FilterResults performFiltering(CharSequence prefix) {
        FilterResults results = new FilterResults();

        if (mUnfilteredData == null) {
            mUnfilteredData = new ArrayList<Map<String, ?>>(mData);
        }

        if (prefix == null || prefix.length() == 0) {
            ArrayList<Map<String, ?>> list = mUnfilteredData;
            results.values = list;
            results.count = list.size();
        } else {
            String prefixString = prefix.toString().toLowerCase();

            ArrayList<Map<String, ?>> unfilteredValues = mUnfilteredData;
            int count = unfilteredValues.size();

            ArrayList<Map<String, ?>> newValues = new ArrayList<Map<String, ?>>(count);

            for (int i = 0; i < count; i++) {
                Map<String, ?> h = unfilteredValues.get(i);
                if (h != null) {

                    int len = mTo.length;

                    for (int j=0; j<len; j++) {
                        String str =  (String)h.get(mFrom[j]);

                        String[] words = str.split(" ");
                        int wordCount = words.length;

                        for (int k = 0; k < wordCount; k++) {
                            String word = words[k];

                            if (word.toLowerCase().startsWith(prefixString)) {
                                newValues.add(h);
                                break;
                            }
                        }
                    }
                }
            }

            results.values = newValues;
            results.count = newValues.size();
        }

        return results;
    }

    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        //noinspection unchecked
        mData = (List<Map<String, ?>>) results.values;
        if (results.count > 0) {
            notifyDataSetChanged();
        } else {
            notifyDataSetInvalidated();
        }
    }
}

} }

Can someone please please help me? 有人可以帮我吗? Thank you! 谢谢!

Hey First replace this code with in DBConnector in display method. 嘿,首先在显示方法中的DBConnector中将此代码替换为。

hm.put("_id", cr.getString(0));

with

hm.put("_id", cr.getInt(0)+"");

and now Post the getView() method of Simple Adapter, or the whole class so I can help you further. 现在发布简单适配器的getView()方法或整个类,以便我进一步帮助您。

okk try to replace 好的,尝试更换

     String text = data == null ? "" : data.toString();

with

     String text = data == null ? "" : (String)data;

put this code in 将此代码放入

  View v;
   if (convertView == null) {
    v = inflater.inflate(resource, parent, false);
    } else {
    v = convertView;
    }

   bindView(position, v);

    return v;

into 进入

  @Override
  public View getDropDownView(int position, View convertView, ViewGroup        parent) {
View v;
if (convertView == null) {
    v = inflater.inflate(resource, parent, false);
} else {
    v = convertView;
}

bindView(position, v);

return v;

} }

hope this work for you. 希望这项工作对您有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM