(追記)
これはバッドノウハウです。
sh_akiraさんが簡単な方法をコメントしてくれました。
BackgroundColorをアルファ付きで指定できるなんて...>_<;
XAMLで作成
普通にOpactiyを設定すると、ラベルの文字も透過されてしまって見づらい。
XAML
<ContentView BackgroundColor="White" Opacity="0.2" Padding="10">
<Label Text="Label" />
</ContentView>
文字は不透明で、背景色のみ半透明にしたい。
Labelの前に半透明のViewをねじ込めば良い感じがするが、
ContentViewは子要素をひとつしか持てない...
では、どうするか?
Gridのひとつのセルに複数の要素を設定すると、重なって表示される挙動を利用する。
XAML
<Grid>
<BoxView Grid.Row="0" Grid.Column="0" BackgroundColor="White" Opacity="0.2" />
<Label Grid.Row="0" Grid.Column="0" Text="Label" Margin="10" VerticalOptions="Center"/>
</Grid>
これでLabelだけ不透明になった。
カスタムUI化
できれば、これをひとつの要素としてXAMLに記述したい。
こんな感じで。
XAML
<local:MyLabel Text="Opacity Label" />
ContentViewを継承したクラスを定義して、XAMLと同等の内容をC#のコードで記載する。
ついでにTextプロパティも追加しておく。
MyView.cs
using System;
using Xamarin.Forms;
namespace SampleApp
{
public class MyLabel : ContentView
{
public static readonly BindableProperty TextProperty = BindableProperty.Create(
"Text", typeof(string), typeof(MyLabel), "Label"
);
public string Text {
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
protected Label _label;
public MyLabel()
{
_label = new Label {
TextColor = Color.Black,
Margin = 10,
VerticalOptions = LayoutOptions.Center
};
BoxView box = new BoxView {
BackgroundColor = Color.White,
Opacity = 0.2f
};
Grid grid = new Grid();
grid.Children.Add(box ,0 ,0);
grid.Children.Add(_label ,0 ,0);
Content = grid;
}
protected override void OnPropertyChanged(string propertyName = null)
{
base.OnPropertyChanged(propertyName);
if (propertyName == TextProperty.PropertyName)
_label.Text = Text;
}
}
}
すると、XAMLで作ったのと同じUIが生成される。
1行で記述できるのでラク&XAMLが見やすくなる。
これが、
XAML
<Grid>
<BoxView Grid.Row="0" Grid.Column="0" BackgroundColor="White" Opacity="0.2" />
<Label Grid.Row="0" Grid.Column="0" Text="Opacity Label" Margin="10" VerticalOptions="Center"/>
</Grid>
こうなる。
XAML
<local:MyLabel Text="Opacity Label" />
角丸にする
共通コード(PCL)では角丸にできないので、カスタムレンダラーを使って各プラットフォームでネイティブ実装する。
iOS
MyLabelRenderer.cs
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using CoreGraphics;
using SampleApp;
using SampleApp.iOS;
[assembly: ExportRenderer(typeof(MyLabel), typeof(MyLabelRenderer))]
namespace SampleApp.iOS
{
public class MyLabelRenderer : VisualElementRenderer<MyLabel>
{
public override void Draw(CGRect rect)
{
base.Draw(rect);
Layer.CornerRadius = 5.0f;
ClipsToBounds = true;
}
}
}
Android
MyLabelRenderer.cs
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Android.Util;
using Android.Graphics;
using SampleApp;
using SampleApp.Droid;
[assembly: ExportRenderer(typeof(MyLabel), typeof(MyLabelRenderer))]
namespace SampleApp.Droid
{
public class MyLabelRenderer : VisualElementRenderer<MyLabel>
{
protected float _radius;
protected Path _path;
public MyViewRenderer()
{
SetWillNotDraw(false);
}
protected override void OnElementChanged(ElementChangedEventArgs<MyLabel> e)
{
base.OnElementChanged(e);
if (e.NewElement != null) {
_radius = TypedValue.ApplyDimension(ComplexUnitType.Dip, 5, Context.Resources.DisplayMetrics);
}
}
protected override void OnSizeChanged(int w, int h, int oldw, int oldh)
{
base.OnSizeChanged(w, h, oldw, oldh);
RectF bounds = new RectF(0, 0, w, h);
_path = new Path();
_path.Reset();
_path.AddRoundRect(bounds, _radius, _radius, Path.Direction.Cw);
_path.Close();
}
public override void Draw(Canvas canvas)
{
canvas.Save();
canvas.ClipPath(_path);
base.Draw(canvas);
canvas.Restore();
}
}
}
完成
背景だけが透過した角丸ラベルができた!
参考
Androidで角丸を実装するにあたり、こちらをパクり参考にしました。
Xamarin Forms – Rounded Corners Content View – QiMata Technologies
http://www.qimata.com/?p=7813