简体   繁体   English

在Listview中更改特定的TextView颜色

[英]Change Specific TextView Color in Listview

i Have Two Database first one Contain All The Items, and the ListView Display it and the second db contain the the Favorite item , [selected from the first database] 我有两个数据库,第一个包含“所有项目”,ListView将其显示,第二个数据库包含“收藏”项目,[从第一个数据库中选择]

what i want is that when the listview display all the items check if the item is already exist in Favoritelist then make that textview background RED for this item 我想要的是当列表视图显示所有项目时,检查该项目是否已存在于收藏夹列表中,然后将该项目的textview背景设为红色

i have this code that work fine 我有这段代码可以正常工作

    public static void ChangeMyFavoritesBG(){

for (int i = 0; i < Items.size(); i++)  {

if(db.verification(Items.get(i).toString())){

try {

TextView favtextview = (TextView) listview.getChildAt(i-listview.getFirstVisiblePosition()).findViewById(R.id.item_name);
 favtextview.setBackgroundResource(R.drawable.redcolor);

}catch (NullPointerException e) {

}}}}

db.verification check if item exist in favorites database if true . db.verification检查项目是否在收藏夹数据库中存在,如果为true。 then it should change the background of this item to red 那么应该将此项的背景更改为红色

this code work fine but only if i put it in button click i need to make the code work automatically but if i made it start automatically when the activity is loaded i get NullPointer Error 此代码可以正常工作,但是只有当我将其放入按钮单击时,我才需要使代码自动工作,但是如果我在加载活动时自动启动代码,则会出现NullPointer错误

i guess because the function ChangeMyFavoritesBG(); 我猜是因为函数ChangeMyFavoritesBG(); work before the listview display items 在listview显示项目之前工作

any idea guys? 有什么主意吗? and sorry for my bad english 对不起,我英语不好

在listView所使用的Adapter的getView(int position, View convertView, ViewGroup parent)方法内执行此控件。

If your favorite is not currently visible in the ListView then getChildAt() will return null. 如果您的收藏夹当前在ListView中不可见,则getChildAt()将返回null。

You are looping over all items in the list view and my guess is that it holds more items than can fit on the screen. 您正在遍历列表视图中的所有项目,我想它所容纳的项目超过了屏幕上的容纳范围。 When your favorite item is one of them then this fragment of your code 当您最喜欢的项目是其中之一时,则此代码片段

listview.getChildAt(i-listview.getFirstVisiblePosition())

will return null. 将返回null。 And that will cause the NullPointerException when you call findViewById(R.id.item_name) on it. 当您在其上调用findViewById(R.id.item_name)时,这将导致NullPointerException。

Just add a check for null on the result of getChildAt(). 只需对getChildAt()的结果添加null的检查。 If it is null then do nothing, if it is non-null then call the second part. 如果为null,则不执行任何操作;如果为非null,则调用第二部分。 This will protect against the exception when your favorite item is not on the screen, and will allow it to be colored red when your favorite is visible on the screen. 当您的收藏夹项目不在屏幕上时,这将防止出现异常,并且当您的收藏夹在屏幕上可见时,它将被涂成红色。

update 更新

My apologies, I read to quickly and misunderstood your problem to be about the NullPointerException but you say that your code works fine when you call it from a button click handler but not when you call it automatically at start-up. 不好意思,我读后很快就误解了关于NullPointerException的问题,但是您说,当您从按钮单击处理程序调用代码时,代码工作正常,但在启动时自动调用代码时,代码工作正常。

You are right, the ListView does not yet have any items loaded when you are still in onCreate(). 没错,当您仍然在onCreate()中时,ListView尚未加载任何项目。 You can add a delay before running you code. 您可以在运行代码之前添加延迟。 The following works for me: 以下对我有用:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_my);

    // initialize the ListView with data for the list items. (I'm using a string array in this 
    // example. You are loading it from a database table, but that is the same in principle.)
    ListAdapter adapter = new ArrayAdapter<String>(this, R.layout.item_list, R.id.item_name, Items);
    ListView listview = (ListView) findViewById(R.id.listview);
    listview.setAdapter(adapter);

    // ask the system to wait before setting the background color of the favorite item so that
    // the ListView has time to load the items.
    final int DELAY_IN_MILLISECONDS = 100;
    listview.postDelayed(new Runnable() {
        @Override
        public void run() {
            ChangeMyFavoritesBG();
        }
    }, DELAY_IN_MILLISECONDS);
}

As you can see in the above example, after initializing the ListView, you ask the system to wait 100 milliseconds before calling ChangeMyFavoritesBG() . 如上例所示,在初始化ListView之后,您要求系统等待100毫秒,然后再调用ChangeMyFavoritesBG() Hopefully that is enough time to load the items from the database into the ListView. 希望有足够的时间将项目从数据库加载到ListView中。 If it is not enough time then you can, of course, use a longer delay. 如果时间不够,那么您当然可以使用更长的延迟。

The alternative 另类

The above should work, but to be honest I would not write it this way. 上面的应该起作用,但是老实说我不会这样写。 The above code is very brittle because it depends on the timing of how long it takes to load the items. 上面的代码非常脆弱,因为它取决于加载项目所需时间的时间。 I recommend that you put your background coloring into a customized adapter. 我建议您将背景色放入自定义的适配器中。

Because you want the items displayed in a customized way -- you want them to have a red background when it is the favorite one -- you should use a customized adapter. 因为您希望项目以自定义的方式显示-您希望它们在收藏夹中显示红色背景-您应该使用自定义的适配器。 Override the bindView() function to make the background red when it is the favorite one or give it a normal background when it is not the favorite. 覆盖bindView()函数,使其成为收藏夹时使背景变为红色,如果不是收藏夹,则将其赋予正常背景。

I don't know how you currently get the items from the database into your ListView, but inheriting from SimpleCursorAdaptor would work pretty well. 我不知道您当前如何将这些项目从数据库中获取到ListView中,但是从SimpleCursorAdaptor继承会很好地工作。

public class FavoritesItemAdapter extends SimpleCursorAdapter {

    public FavoritesItemAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) {
        super(context, layout, c, from, to, flags);
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        super.bindView(view, context, cursor);

        // read the name from the database
        int nameColumnIndex = cursor.getColumnIndexOrThrow("name");
        String name = cursor.getString(nameColumnIndex);

        // write the name to the TextView
        TextView nameText = (TextView) view.findViewById(R.id.item_name);
        nameText.setText(name);

        // set the background to normal or to red, depending on if it is the favorite one or not
        boolean isFavorite = db_verification(name);
        if (isFavorite) {
            nameText.setBackgroundResource(R.drawable.redcolor);
        } else {
            nameText.setBackgroundResource(android.R.color.transparent);
        }
    }

    public boolean db_verification(String name) {
        // this is a stub. You must use your own code here
        return name.equals("the favorite one");
    }
}

You can then throw away ChangeMyFavoritesBG() and initialize your ListView with the adapter in onCreate() like this. 然后,您可以扔掉ChangeMyFavoritesBG()并使用onCreate()中的适配器初始化ListView,如下所示。

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_my);

    Cursor cursor = readItemsFromDatabase();        
    String[] from = new String[] { "name_column" }; // mapping from database column name ...
    int[] to = new int[] { R.id.item_name };        // ... to View ID in the item's layout.
    FavoritesItemAdapter adapter = new FavoritesItemAdapter(this, R.layout.item_list, cursor, from, to, 0);

    ListView listview = (ListView) findViewById(R.id.listview);
    listview.setAdapter(adapter);
}

Good luck! 祝好运!

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

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