LoginSignup
4
3

More than 5 years have passed since last update.

Xamarin.FormsでListViewの選択行ハイライト色を変える

Last updated at Posted at 2017-05-29

ListView の選択行のハイライト色を設定するプロパティが用意されていないとかふざけてるんで、自前で作るしかないようです。

実現手段の概要

基本的にカスタムレンダラー対応。

ListView をタップして行(セル)が選択されると、その行の View たる ViewCell に PropertyChanged が送られるようなので、それを利用。

ViewCell クラスのプロパティにそんなのは存在しないが、ともかく送られてくる。OnPropertyChanged で見張っていると判る。

しかし送られて来るのはAndroidのみでiOSだと送られて来ない。
なのでiOSはカスタムレンダラー必須。面倒臭すぎ。

コード

PCL

XAML
<?xml version="1.0" encoding="utf-8"?>
<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:v="clr-namespace:MyApp.Views"
    xmlns:vm="clr-namespace:MyApp.ViewModels"
    Padding="30"
    x:Class="MyApp.Views.MainPage">

    <ContentPage.BindingContext>
        <vm:MainPageViewModel />
    </ContentPage.BindingContext>

    <StackLayout>
        <ContentView BackgroundColor="Gray" Padding="5">
            <ListView ItemsSource="{Binding Items}" BackgroundColor="White" HasUnevenRows="false" RowHeight="40">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <v:MyViewCell SelectedBackgroundColor="Red">
                            <ContentView>
                                <StackLayout Orientation="Horizontal">
                                    <Label Text="{Binding}" TextColor="Black" VerticalTextAlignment="Center" />
                                </StackLayout>
                            </ContentView>
                        </v:MyViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </ContentView>
    </StackLayout>

</ContentPage>
View
using Xamarin.Forms;

namespace MyApp.Views
{
    public class MyViewCell : ViewCell
    {
        public static readonly BindableProperty SelectedBackgroundColorProperty = BindableProperty.Create(
            "SelectedBackgroundColor", typeof(Color), typeof(MyViewCell), Color.Default
        );

        public Color SelectedBackgroundColor {
            get { return (Color)GetValue(SelectedBackgroundColorProperty); }
            set { SetValue(SelectedBackgroundColorProperty, value);}
        }

        public MyViewCell()
        {
        }
    }
}
ViewModel
using System.Collections.Generic;

namespace MyApp.ViewModels
{
    public class MainPageViewModel
    {
        public List<string> Items { protected set; get; } = new List<string>();

        public MainPageViewModel()
        {
            Items.Add("First Item");
            Items.Add("Second Item");
        }
    }
}

iOS

カスタムレンダラー
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

using UIKit;

using MyApp.Views;
using MyApp.iOS.Renderers;

[assembly: ExportRenderer(typeof(MyViewCell), typeof(MyViewCellRenderer))]

namespace MyApp.iOS.Renderers
{
    public class MyViewCellRenderer: ViewCellRenderer
    {
        public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
        {
            var cell = base.GetCell(item, reusableCell, tv);

            cell.SelectedBackgroundView = new UIView
            {
                BackgroundColor = ((MyViewCell)item).SelectedBackgroundColor.ToUIColor()
            };

            return cell;
        }
    }
}

Android

カスタムレンダラー
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

using MyApp.Views;
using MyApp.Droid.Renderers;

[assembly: ExportRenderer(typeof(MyViewCell), typeof(MyViewCellRenderer))]

namespace MyApp.Droid.Renderers
{
    public class MyViewCellRenderer: ViewCellRenderer
    {
        private Android.Views.View _cellCore;
        private bool _selected;
        private Android.Graphics.Drawables.Drawable _unselectedBackground;

        protected override Android.Views.View GetCellCore(Cell item, Android.Views.View convertView, Android.Views.ViewGroup parent, Android.Content.Context context)
        {
            _cellCore = base.GetCellCore(item, convertView, parent, context);

            this._selected = false;
            this._unselectedBackground = _cellCore.Background;

            return _cellCore;
        }

        protected override void OnCellPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnCellPropertyChanged(sender, e);

            if (e.PropertyName == "IsSelected") {
                _selected = !(_selected);
                if (_selected) {
                    _cellCore.SetBackgroundColor(((MyViewCell)sender).SelectedBackgroundColor.ToAndroid());
                } else {
                    _cellCore.SetBackground(this._unselectedBackground);
                }
            }
        }
    }
}

結果

ios.png

android.png

両OSともハイライト色が赤くなりました。
うまくいっているようです。

AndroidをPCLだけでなんとかするケース

前述のとおり、iOSでは IsSelected を捕捉できないっぽいので、これが通用するのはAndroidだけです。

View
ing Xamarin.Forms;

namespace MyApp.Views
{
    public class MyViewCell : ViewCell
    {
        public static readonly BindableProperty SelectedBackgroundColorProperty = BindableProperty.Create(
            "SelectedBackgroundColor", typeof(Color), typeof(MyViewCell), Color.Default
        );

        public Color SelectedBackgroundColor {
            get { return (Color)GetValue(SelectedBackgroundColorProperty); }
            set { SetValue(SelectedBackgroundColorProperty, value);}
        }

        protected Color _UnselectedBackgroundColor;
        protected bool _selected;

        public MyViewCell()
        {
            this._selected = false;
        }

        protected override void OnPropertyChanged(string propertyName = null)
        {
            base.OnPropertyChanged(propertyName);

            if (propertyName == "IsSelected") {
                this._selected = !(this._selected);
                if (this._selected) {
                    if (this._UnselectedBackgroundColor == null) {
                        this._UnselectedBackgroundColor = this.View.BackgroundColor;
                    }
                    this.View.BackgroundColor = this.SelectedBackgroundColor;
                } else {
                    this.View.BackgroundColor = this._UnselectedBackgroundColor;
                }
            }
        }
    }
}

とりあえずは以上です。

こちらを参考にしパクリました

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3