问题
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