Difference between tinting a child View and the containing ViewGroup

。_饼干妹妹 提交于 2019-12-13 03:08:54

问题


I'm trying to better understand the following situation that arose while refactoring some "selection highlighting" code (to take advantage of tinting).

There's a list that's populated with an adapter, CodebookAdapter, where each item's defined as:

CodebookAdapter List Item Layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:background="#FFFFFFFF">

    <ImageView
      android:id="@+id/item_icon_iv"
      android:layout_width="36dp"
      android:layout_height="36dp"
      android:layout_gravity="center_vertical" />    

    <TextView
      android:id="@+id/item_header_tv"
      android:layout_width="match_parent"
      android:layout_height="20dp"      
      android:textColor="#FF000000"
      android:textSize="14dp"/>
      <!--android:background="#FFFFFFFF"-->
</LinearLayout>

The method below, HiliteCodeItem(), sets the TextView, item_header_tv, to selected.

I've set the background-tint first on the list-item itself, and then just on the enclosed TextView (to avoid undesired highlighting of the entire layout):

// option 1 - item_header_tv's background can be omitted/null, highlights ok
/////////////////////////////////////////////////////////////
v.Background.SetTintList(_csl);

// option 2 - item_header_tv's background cannot be omitted/null
/////////////////////////////////////////////////////////////
tv.Background.SetTintList(_csl);

Why if in option 2 the background must be explicitly set (or else tv.Background.SetTintList(_csl); throws null ex), but in option 1 item_header_tv's background get's highlighted?

Is the enclosing list item's LinearLayout doing a null check on the background of TextView and instantiating one?

public class Codebook : LinearLayout
{  
     protected virtual void HiliteCodeItem(TextView codeDesc, Code code)        
    {
        _codebookAdapter.SelectedCode = code;

        //codeDesc.SetBackgroundColor(SelectedCodeListItemBgColor);
        codeDesc.Selected = true;       

        _codebookAdapter.NotifyDataSetChanged();
    }

    protected class CodebookAdapter : ArrayAdapter<Code>
    {
        private Codebook _; // explicit outer object ref
        private int _listItemRes;
        private List<Code> _items;    
        private Android.Content.Res.ColorStateList _csl;

        public Code SelectedCode { get; set; }

        public CodebookAdapter(Context context, int listItemRes, List<Code> items, Codebook outer)
            : base(context, listItemRes.Layout, items)
        {
            _ = outer;
            _listItemRes = listItemRes;
            _items = items;

            _csl = _._context.Resources.GetColorStateList(Resource.Color.codebook_code_list_item_color_state_list);
        }

        public override View GetView(int position, View convertView, ViewGroup parent)
        {
            View v = convertView;
            TextView tv;

            if (v == null)
            {   
                v = _._inflater.Inflate(_listItemRes, parent, false);
                tv = v.FindViewById<TextView>(Resource.Id.item_header_tv);

                // option 1 - item_header_tv's background can be omitted/null, highlights ok
                /////////////////////////////////////////////////////////////
                v.Background.SetTintList(_csl);

                // option 2 - item_header_tv's background cannot be omitted/null
                /////////////////////////////////////////////////////////////
                tv.Background.SetTintList(_csl);
            }
            else
                tv = v.FindViewById<TextView>(Resource.Id.item_header_tv);              

            if (_items == null || _items.Count == 0)
            {
                return v;
            }

            Code code = _items[position];

            if (code != null)
            {   
                if (code == SelectedCode)
                {
                    //tvCodeHeader.SetBackgroundColor(_.SelectedCodeListItemBgColor);
                    tvCodeHeader.Selected = true;
                }
                else
                {
                    //tvCodeHeader.SetBackgroundColor(_.UnselectedCodeListItemBgColor);
                    tvCodeHeader.Selected = false;
                }
            }
        }
    }
}

回答1:


Why if in option 2 the background must be explicitly set (or else tv.Background.SetTintList(_csl); throws null ex), but in option 1 item_header_tv's background get's highlighted?

The first works because you've set android:background="#FFFFFFFF" to the LinearLayout, the code v = _._inflater.Inflate(_listItemRes, parent, false); points to the this LinearLayout. So it's background is not omitted/null.

The Background cannot be null if you want to SetTintList, the second line doesn't work because Background of your TextView v is null.

By the way, controls like Button has Background set by default, you don't need to specify the Background property for them to use SetTintList.



来源:https://stackoverflow.com/questions/47043218/difference-between-tinting-a-child-view-and-the-containing-viewgroup

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!