【问题标题】:Changing the BackgroundResource of a ListView Object while it's off screen在屏幕外更改 ListView 对象的 BackgroundResource
【发布时间】:2020-02-09 02:13:35
【问题描述】:

新手在这里做课程作业。

我正在制作一个 Xamarin C# 应用程序,您可以在其中创建一个对象列表,这些对象显示在 UI 中,目的是跟踪桌面/棋盘游戏中的回合。 为了显示轮到谁,当你点击一个旋转按钮时,轮到他们的对象的 ListView 单元格会改变颜色,而其他的则设置为白色。 如果屏幕太小或屏幕外有任何对象,应用程序在按下旋转按钮时会崩溃。

如何防止这种崩溃?我可以将数据保存在内存中,这样当你向下滚动时,轮到他们的单位会是蓝色的? ListView 能做到这一点吗?

这是按钮的工作原理

Button _rotateButton = FindViewById<Button>(Resource.Id.rotateButton);
        int rotatePrevious = -1;
        int rotateCurrent = 0;

        _rotateButton.Click += delegate
        {
            int rotateCount = ItemUnits.Count();

            if(rotateCount != 0)
            { 

            if (rotateCurrent == 0)
            {
                _rotateButton.Text = "End Turn";

            }

            if(rotatePrevious != -1)
                {
                    ItemUnits[rotatePrevious].IsSelected = false;
                }

                if (rotateCurrent == rotateCount)
                {

                    foreach(ItemUnit iu in ItemUnits)
                    {
                        iu.IsSelected = false;
                        View inactiveView = listView.GetChildAt(ItemUnits.IndexOf(iu));
                        inactiveView.SetBackgroundResource(Resource.Color.colorPrimary);
                    }
                    rotateCurrent = 0;
                    rotatePrevious = -1;
                    _rotateButton.Text = "New Round";
                }

                else
                {
                    ItemUnits[rotateCurrent].IsSelected = true;

                    foreach (ItemUnit iu in ItemUnits)
                    {
                        if (iu.IsSelected == true)
                        {
                            View activeView = listView.GetChildAt(ItemUnits.IndexOf(iu));
                            activeView.SetBackgroundResource(Resource.Color.colorAccent);
                        }
                        else
                        {
                            View inactiveView = listView.GetChildAt(ItemUnits.IndexOf(iu));
                            inactiveView.SetBackgroundResource(Resource.Color.colorPrimary);
                        }

                    }


                    rotateCurrent++;
                    rotatePrevious++;

                    if (rotateCurrent == rotateCount)
                    {
                        _rotateButton.Text = "End Round";
                    }
                }

            }

【问题讨论】:

  • 导致崩溃的具体行是什么?有什么例外?
  • 当它试图更改 BackgroundResrouce 时,它​​只是一个空引用异常,因为它试图引用不在屏幕上的 ListView 单元格,我认为这意味着它在上下文中不存在。所以我正在寻找解决方法。

标签: c# android listview xamarin


【解决方案1】:

你想达到像下面的GIF这样的效果吗?

如果是这样,您可以在适配器中添加setSelectedId 方法。然后像下面的代码一样改变背景颜色。

   public class ListViewAdapter : BaseAdapter<Meeting>
{
    private Activity activity;
    private List<Meeting> listMeeting;
    public ListViewAdapter(Activity activity, List<Meeting> listMeeting)
    {
        this.activity = activity;
        this.listMeeting = listMeeting;
    }

    public override Meeting this[int position] => listMeeting[position];

    public override int Count
    {
        get { return listMeeting.Count; }
    }

    public override long GetItemId(int position)
    {
        return listMeeting[position].Id;
    }
    private int selectedId = -1;
    public void setSelectedId(int position)
    {
        selectedId = position;
    }

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        View view = convertView;
        if (view == null) // no view to re-use, create new
            view = activity.LayoutInflater.Inflate(Resource.Layout.list_view, null);


        var txtName = view.FindViewById<TextView>(Resource.Id.idLogin);
        var txtDepart = view.FindViewById<TextView>(Resource.Id.idContact);
        var txtEmail = view.FindViewById<TextView>(Resource.Id.Place);
        txtName.Text = listMeeting[position].idLogin.ToString();
        txtDepart.Text = listMeeting[position].idContact.ToString();
        txtEmail.Text = listMeeting[position].Place;

        if (selectedId == position)
        {
            view.SetBackgroundColor(Color.Red);

        }
        else
        {
            view.SetBackgroundColor(Color.Transparent);

        }


        return view;
    }


}

使用此方法,按位置改变颜色。

    private void BtnAdd_Click(object sender, EventArgs e)
    {
        adapter.setSelectedId(Int32.Parse(edtidLogin.Text));
        adapter.NotifyDataSetChanged();
    }

这是我的活动代码。

     protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        Xamarin.Essentials.Platform.Init(this, savedInstanceState);
        // Set our view from the "main" layout resource
        SetContentView(Resource.Layout.activity_main);
        lstViewData = FindViewById<ListView>(Resource.Id.listView);
         edtidLogin = FindViewById<EditText>(Resource.Id.edtidLogin); 
        var btnChange = FindViewById<Button>(Resource.Id.btnChange);
        listSource.Add(new Meeting() { idContact=1, idLogin=1, Place="test1" });
        listSource.Add(new Meeting() { idContact = 2, idLogin = 1, Place = "test2" });
        listSource.Add(new Meeting() { idContact = 3, idLogin = 1, Place = "test3" });
        listSource.Add(new Meeting() { idContact = 4, idLogin = 1, Place = "test4" });
        listSource.Add(new Meeting() { idContact = 5, idLogin = 1, Place = "test5" });
        listSource.Add(new Meeting() { idContact = 6, idLogin = 1, Place = "test6" });
        listSource.Add(new Meeting() { idContact = 7, idLogin = 1, Place = "test7" });
        listSource.Add(new Meeting() { idContact = 8, idLogin = 1, Place = "test8" });
        listSource.Add(new Meeting() { idContact = 9, idLogin = 1, Place = "test9" });
        listSource.Add(new Meeting() { idContact = 10, idLogin = 1, Place = "test10" });
        listSource.Add(new Meeting() { idContact = 11, idLogin = 1, Place = "test11" });
        listSource.Add(new Meeting() { idContact = 12, idLogin = 1, Place = "test12" });
        listSource.Add(new Meeting() { idContact = 13, idLogin = 1, Place = "test13" });
        listSource.Add(new Meeting() { idContact = 14, idLogin = 1, Place = "test14" });
        listSource.Add(new Meeting() { idContact = 15, idLogin = 1, Place = "test15" });
        listSource.Add(new Meeting() { idContact = 16, idLogin = 1, Place = "test16" });

        adapter = new ListViewAdapter(this, listSource);
        lstViewData.Adapter = adapter;

        btnChange.Click += BtnAdd_Click;

    }

    private void BtnAdd_Click(object sender, EventArgs e)
    {
        adapter.setSelectedId(Int32.Parse(edtidLogin.Text));
        adapter.NotifyDataSetChanged();
    }

【讨论】:

  • 在将我的代码与您的方法混合使用时遇到一些问题,并且我不断出现超出范围的异常和其他一些问题,所以我只是想让它工作......仍然没有运气。我会在它运行时回复你。
  • 花了一些时间,但我使用 adapter.setSelectedId 方法让它工作了。我没有使用您发布的方法,但您提供的方法在使用我的解决方案时有效。非常感谢!
  • Lu 还有一个问题是你知道如何设置它以便不选择任何项目吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-06
  • 1970-01-01
相关资源
最近更新 更多