J'ai créé un bouton triangulaire dans android. Ça marche bien. Je veux juste changer la couleur de remplissage/couleur de trait quand le bouton est survolé/pressé (comme dans le bouton par défaut).bouton Triangle android cliquez/hovered
Je tente d'invalider l'affichage lorsque la propriété survolée a changé et que la couleur de la méthode OnDraw a été modifiée sans succès.
Ceci est mon code:
public enum TriangularButtonDirection
{
Up = 0,
Down = 1
}
class TriangularButton : Button
{
public TriangularButton(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
this.Initialize(null);
}
public TriangularButton(Context context) : base(context)
{
this.Initialize(null);
}
public TriangularButton(Context context, IAttributeSet attrs) : base(context, attrs)
{
this.Initialize(attrs);
}
public TriangularButton(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)
{
this.Initialize(attrs);
}
public TriangularButton(Context context, IAttributeSet attrs, int defStyleAttr, int defStyleRes) : base(context, attrs, defStyleAttr, defStyleRes)
{
this.Initialize(attrs);
}
private TriangularButtonDirection _direction = TriangularButtonDirection.Down;
private void Initialize(IAttributeSet attributeSet)
{
if (attributeSet != null)
{
TypedArray a = this.Context.ObtainStyledAttributes(attributeSet, Resource.Styleable.TriangularButton);
int direction = a.GetInt(Resource.Styleable.TriangularButton_direction, -1);
if (direction > -1)
this._direction = (TriangularButtonDirection)direction;
a.Recycle();
}
}
public override bool OnTouchEvent(MotionEvent e)
{
float x = e.GetX();
float y = e.GetY();
int width = this.MeasuredWidth;
PointF point1Draw;
PointF point2Draw;
PointF point3Draw;
if (this._direction == TriangularButtonDirection.Up)
{
point1Draw = new PointF(0, 3f * width/4);
point2Draw = new PointF(width, 3f * width/4);
point3Draw = new PointF(width/2f, 0);
}
else
{
point1Draw = new PointF(0, 0);
point2Draw = new PointF(width, 0);
point3Draw = new PointF(width/2f, 3f * width/4);
}
bool test = PointInTriangle(new PointF(x, y), point1Draw, point2Draw, point3Draw);
if (test)
base.OnTouchEvent(e);
return (test);
}
public static bool PointInTriangle(PointF p, PointF p0, PointF p1, PointF p2)
{
float s = p0.Y * p2.X - p0.X * p2.Y + (p2.Y - p0.Y) * p.X + (p0.X - p2.X) * p.Y;
float t = p0.X * p1.Y - p0.Y * p1.X + (p0.Y - p1.Y) * p.X + (p1.X - p0.X) * p.Y;
if ((s < 0) != (t < 0))
return false;
float a = -p1.Y * p2.X + p0.Y * (p2.X - p1.X) + p0.X * (p1.Y - p2.Y) + p1.X * p2.Y;
if (a < 0.0)
{
s = -s;
t = -t;
a = -a;
}
return s > 0 && t > 0 && (s + t) <= a;
}
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
base.OnMeasure(widthMeasureSpec, heightMeasureSpec);
this.SetMeasuredDimension(this.MeasuredWidth, 3 * this.MeasuredWidth/4);
}
public override void Draw(Canvas canvas)
{
int width = this.MeasuredWidth;
Paint paintFill = new Paint(PaintFlags.AntiAlias);
paintFill.StrokeWidth = 2;
paintFill.Color = this.Hovered ? Color.Red : new Color(242, 180, 54);
paintFill.SetStyle(Android.Graphics.Paint.Style.Fill);
paintFill.AntiAlias = true;
Paint paintStroke = new Paint(PaintFlags.AntiAlias);
paintStroke.StrokeWidth = 2;
paintStroke.Color = Color.White;
paintStroke.SetStyle(Android.Graphics.Paint.Style.Stroke);
paintStroke.AntiAlias = true;
PointF point1Draw;
PointF point2Draw;
PointF point3Draw;
if (this._direction == TriangularButtonDirection.Up)
{
point1Draw = new PointF(0, 3f * width/4);
point2Draw = new PointF(width, 3f * width/4);
point3Draw = new PointF(width/2f, 0);
}
else
{
point1Draw = new PointF(0, 0);
point2Draw = new PointF(width, 0);
point3Draw = new PointF(width/2f, 3f * width/4);
}
Path path = new Path();
path.SetFillType(Path.FillType.EvenOdd);
path.MoveTo(point1Draw.X, point1Draw.Y);
path.LineTo(point2Draw.X, point2Draw.Y);
path.LineTo(point3Draw.X, point3Draw.Y);
path.LineTo(point1Draw.X, point1Draw.Y);
path.Close();
canvas.DrawPath(path, paintFill);
canvas.DrawPath(path, paintStroke);
}
}
EDIT: code final
class TriangularButton : Button
{
public TriangularButton(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
this.Initialize(null);
}
public TriangularButton(Context context) : base(context)
{
this.Initialize(null);
}
public TriangularButton(Context context, IAttributeSet attrs) : base(context, attrs)
{
this.Initialize(attrs);
}
public TriangularButton(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)
{
this.Initialize(attrs);
}
public TriangularButton(Context context, IAttributeSet attrs, int defStyleAttr, int defStyleRes) : base(context, attrs, defStyleAttr, defStyleRes)
{
this.Initialize(attrs);
}
private TriangularButtonDirection _direction = TriangularButtonDirection.Down;
private TriangularButtonState _state = TriangularButtonState.Normal;
private Paint _paintFillNormal;
private Paint _paintStrokeNormal;
private Paint _paintFillPressed;
private Paint _paintStrokePressed;
private void Initialize(IAttributeSet attributeSet)
{
if (attributeSet != null)
{
TypedArray a = this.Context.ObtainStyledAttributes(attributeSet, Resource.Styleable.TriangularButton);
int direction = a.GetInt(Resource.Styleable.TriangularButton_direction, -1);
if (direction > -1)
this._direction = (TriangularButtonDirection)direction;
a.Recycle();
}
this._paintFillNormal = new Paint(PaintFlags.AntiAlias);
this._paintFillNormal.StrokeWidth = 2;
this._paintFillNormal.Color = new Color(242, 180, 54);
this._paintFillNormal.SetStyle(Android.Graphics.Paint.Style.Fill);
this._paintFillNormal.AntiAlias = true;
this._paintFillPressed = new Paint(PaintFlags.AntiAlias);
this._paintFillPressed.StrokeWidth = 2;
this._paintFillPressed.Color = new Color(255, 255, 255, 51);
this._paintFillPressed.SetStyle(Android.Graphics.Paint.Style.Fill);
this._paintFillPressed.AntiAlias = true;
this._paintStrokeNormal = new Paint(PaintFlags.AntiAlias);
this._paintStrokeNormal.StrokeWidth = 2;
this._paintStrokeNormal.Color = Color.White;
this._paintStrokeNormal.SetStyle(Android.Graphics.Paint.Style.Stroke);
this._paintStrokeNormal.AntiAlias = true;
this._paintStrokePressed = new Paint(PaintFlags.AntiAlias);
this._paintStrokePressed.StrokeWidth = 2;
this._paintStrokePressed.Color = new Color(51, 51, 51, 51);
this._paintStrokePressed.SetStyle(Android.Graphics.Paint.Style.Stroke);
this._paintStrokePressed.AntiAlias = true;
}
private bool _isEnabled;
public override bool Enabled
{
get => this._isEnabled;
set
{
if (this._isEnabled != value)
{
this._isEnabled = value;
this.Invalidate();
}
}
}
public override bool OnTouchEvent(MotionEvent e)
{
if (!this._isEnabled)
return (false);
float x = e.GetX();
float y = e.GetY();
int width = this.MeasuredWidth;
PointF point1Draw;
PointF point2Draw;
PointF point3Draw;
if (this._direction == TriangularButtonDirection.Up)
{
point1Draw = new PointF(0, 3f * width/4);
point2Draw = new PointF(width, 3f * width/4);
point3Draw = new PointF(width/2f, 0);
}
else
{
point1Draw = new PointF(0, 0);
point2Draw = new PointF(width, 0);
point3Draw = new PointF(width/2f, 3f * width/4);
}
bool test = PointInTriangle(new PointF(x, y), point1Draw, point2Draw, point3Draw);
if (test)
{
base.OnTouchEvent(e);
}
switch (e.Action)
{
case MotionEventActions.Down:
this._state = TriangularButtonState.Pressed;
test = true;
this.Invalidate();
break;
case MotionEventActions.HoverEnter:
this._state = TriangularButtonState.Hovered;
this.Invalidate();
break;
case MotionEventActions.Up:
this._state = TriangularButtonState.Normal;
this.Invalidate();
break;
case MotionEventActions.HoverExit:
this._state = TriangularButtonState.Normal;
this.Invalidate();
break;
}
return (test);
}
public static bool PointInTriangle(PointF p, PointF p0, PointF p1, PointF p2)
{
float s = p0.Y * p2.X - p0.X * p2.Y + (p2.Y - p0.Y) * p.X + (p0.X - p2.X) * p.Y;
float t = p0.X * p1.Y - p0.Y * p1.X + (p0.Y - p1.Y) * p.X + (p1.X - p0.X) * p.Y;
if ((s < 0) != (t < 0))
return false;
float a = -p1.Y * p2.X + p0.Y * (p2.X - p1.X) + p0.X * (p1.Y - p2.Y) + p1.X * p2.Y;
if (a < 0.0)
{
s = -s;
t = -t;
a = -a;
}
return s > 0 && t > 0 && (s + t) <= a;
}
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
base.OnMeasure(widthMeasureSpec, heightMeasureSpec);
this.SetMeasuredDimension(this.MeasuredWidth, 3 * this.MeasuredWidth/4);
}
public override void Draw(Canvas canvas)
{
int width = this.MeasuredWidth;
PointF point1Draw;
PointF point2Draw;
PointF point3Draw;
if (this._direction == TriangularButtonDirection.Up)
{
point1Draw = new PointF(0, 3f * width/4);
point2Draw = new PointF(width, 3f * width/4);
point3Draw = new PointF(width/2f, 0);
}
else
{
point1Draw = new PointF(0, 0);
point2Draw = new PointF(width, 0);
point3Draw = new PointF(width/2f, 3f * width/4);
}
Path path = new Path();
path.SetFillType(Path.FillType.EvenOdd);
path.MoveTo(point1Draw.X, point1Draw.Y);
path.LineTo(point2Draw.X, point2Draw.Y);
path.LineTo(point3Draw.X, point3Draw.Y);
path.LineTo(point1Draw.X, point1Draw.Y);
path.Close();
if (!this.Enabled)
{
canvas.DrawPath(path, this._paintStrokeNormal);
}
else
{
canvas.DrawPath(path, this._state == TriangularButtonState.Normal ? this._paintFillNormal : this._paintFillPressed);
canvas.DrawPath(path, this._state == TriangularButtonState.Normal ? this._paintStrokeNormal : this._paintStrokePressed);
}
}
}
Merci pour l'aide
Je ne comprends pas , est-ce un projet Xamarin.Android? Pourquoi voulez-vous créer une sous-classe de 'Button'? Habituellement, nous personnalisons un 'Button' directement en XML. –
Oui, j'utilise Xamarin.Android. Je peux personnaliser le bouton mais je ne peux pas avoir le résultat désiré. Les triangles avec bordure ne sont pas possibles avec le fichier de style ... – Geotinc