C# 三角形按钮安卓点击/悬停
我在android中创建了一个三角形按钮。它工作得很好。 我只想在按钮悬停/按下时更改填充颜色/笔划颜色(如默认按钮) 我试图在hovered属性更改时使视图无效,并在OnDraw方法中更改颜色,但没有成功 这是我的代码:C# 三角形按钮安卓点击/悬停,c#,android,xamarin,C#,Android,Xamarin,我在android中创建了一个三角形按钮。它工作得很好。 我只想在按钮悬停/按下时更改填充颜色/笔划颜色(如默认按钮) 我试图在hovered属性更改时使视图无效,并在OnDraw方法中更改颜色,但没有成功 这是我的代码: public enum TriangularButtonDirection { Up = 0, Down = 1 } class TriangularButton : Button { public TriangularButton(IntPtr j
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);
}
}
public enum TriangularButtonDirection
{
Up=0,
向下=1
}
类三角形按钮:按钮
{
公共三角按钮(IntPtr javaReference,JniHandleOwnership transfer):base(javaReference,transfer)
{
初始化(null);
}
公共三角形按钮(上下文):基础(上下文)
{
初始化(null);
}
公共三角形按钮(上下文,IAttributeSet属性):基本(上下文,属性)
{
初始化(attrs);
}
公共三角形按钮(上下文,IAttributeSet属性,int defStyleAttr):基(上下文,属性,defStyleAttr)
{
初始化(attrs);
}
公共三角形按钮(上下文上下文、IAttributeSet属性、int-defstylettr、int-defStyleRes):基本(上下文、属性、defStyleAttr、defStyleRes)
{
初始化(attrs);
}
private TriangularButtonDirection _direction=TriangularButtonDirection.Down;
私有void初始化(IAttributeSet attributeSet)
{
if(attributeSet!=null)
{
TypedArray a=this.Context.ActainStyledAttributes(attributeSet,Resource.Styleable.TriangularButton);
int direction=a.GetInt(Resource.Styleable.TriangularButton_direction,-1);
如果(方向>-1)
此._方向=(三角形按钮方向)方向;
a、 回收();
}
}
公共覆盖bool ONTOUCHENT(运动事件e)
{
float x=e.GetX();
float y=e.GetY();
int-width=此.MeasuredWidth;
PointF point1Draw;
点f点2draw;
PointF point3Draw;
if(this._direction==TriangularButtonDirection.Up)
{
point1Draw=新的PointF(0,3f*宽度/4);
point2Draw=新的PointF(宽度,3f*宽度/4);
point3Draw=新的PointF(宽度/2f,0);
}
其他的
{
point1Draw=新的PointF(0,0);
point2Draw=新的PointF(宽度,0);
point3Draw=新的PointF(宽度/2f,3f*宽度/4);
}
布尔测试=点三角形(新点F(x,y)、点1Draw、点2Draw、点3Draw);
如果(测试)
基孔(e);
返回(测试);
}
公共静态布尔点三角形(点F p、点F p0、点F p1、点F p2)
{
浮点s=p0.Y*p2.X-p0.X*p2.Y+(p2.Y-p0.Y)*p.X+(p0.X-p2.X)*p.Y;
浮动t=p0.X*p1.Y-p0.Y*p1.X+(p0.Y-p1.Y)*p.X+(p1.X-p0.X)*p.Y;
如果((s<0)!=(t<0))
返回false;
浮点a=-p1.Y*p2.X+p0.Y*(p2.X-p1.X)+p0.X*(p1.Y-p2.Y)+p1.X*p2.Y;
如果(a<0.0)
{
s=-s;
t=-t;
a=-a;
}
返回s>0&&t>0&&t(s+t)-1)
此._方向=(三角形按钮方向)方向;
a、 回收();
}
此._paintFillNormal=新油漆(PaintFlags.antialas);
这._paintFillNormal.StrokeWidth=2;
这._paintFillNormal.Color=新颜色(242、180、54);
这个.u paintFillNormal.SetStyle(Android.Graphics.Paint.Style.Fill);
这是._paintFillNormal.antialas=true;
此._paintFillPressed=新油漆(PaintFlags.antialas);
这._paintFillPressed.StrokeWidth=2;
此._paintFillPressed.Color=新颜色(255、255、255、51);
这个.u paintFillPressed.SetStyle(Android.Graphics.Paint.Style.Fill);
这是._paintFillPressed.antialas=true;
此._paintStrokeNormal=新油漆(PaintFlags.antialas);
这一点。_paintStrokeNormal.StrokeWidth=2;
这个._paintStrokeNormal.Color=Color.White;
这个.u paintStrokeNormal.SetStyle(Android.Graphics.Paint.Style.Stroke);
此项。_paintStrokeNormal.antialas=true;
此._paintStrokePressed=新油漆(PaintFlags.antialas);
这是._paintStrokePressed.StrokeWidth=2;
此._paintStrokePressed.Color=新颜色(51,51,51,51);
这个.u paintStrokePressed.SetStyle(Android.Graphics.Paint.Style.Stroke);
此项。_paintStrokePressed.antialas=true;
}
私人住宅已启用;
公共覆盖布尔已启用
{
get=>这个;
设置
{
如果(此项已启用!=值)
{
此项。_isEnabled=值;
这个。使无效();
}
}
}
公共覆盖bool ONTOUCHENT(运动事件e)
{
如果(!此项已启用)
返回(假);
float x=e.GetX();
float y=e.GetY();
int-width=此.MeasuredWidth;
PointF point1Draw;
点f点2draw;
PointF point3Draw;
if(this._direction==TriangularButtonDirection.Up)
{
point1Draw=新的PointF(0,3f*宽度/4);
point2Draw=新的PointF(宽度,3f*宽度/4);
point3Draw=新的PointF(宽度/2f,0);
}
其他的
{
point1Draw=新的PointF(0,0);
point2Draw=新的PointF(宽度,0);
point3Draw=新的PointF(宽度/2f,3f*宽度/4);
}
布尔测试=点三角形(新点F(x,y)、点1Draw、点2Draw、点3Draw);
如果(测试)
{
基孔(e);
}
开关(电动)
{
案例MotionEventActions.Down:
此._state=TriangularButtonState.Pressed;
测试=真;
这个。使无效();
打破
case MotionEventActions.HoverEnter:
这个州=
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);
}
}
}
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<rotate
android:fromDegrees="45"
android:toDegrees="45"
android:pivotX="-40%"
android:pivotY="87%">
<shape
android:shape="rectangle">
<stroke android:color="#800000" android:width="5dp" />
<solid
android:color="#ee9ca8" />
</shape>
</rotate>
</item>
</layer-list>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/triangleClick" />
<!-- pressed -->
<item android:state_focused="true"
android:drawable="@drawable/triangleHover" />
<!-- focused -->
<item android:drawable="@drawable/triangleNormal" />
<!-- default -->
</selector>
<Button android:layout_height="70dp"
android:layout_width="70dp"
android:layout_gravity="center_horizontal"
android:background="@drawable/triangleSelector"
style="?android:attr/borderlessButtonStyle" />
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<rotate
android:fromDegrees="45"
android:toDegrees="45"
android:pivotX="-40%"
android:pivotY="87%">
<shape
android:shape="rectangle">
<stroke android:color="#800000" android:width="5dp" />
<solid
android:color="#ee9ca8" />
</shape>
</rotate>
</item>
<item android:top="65dp" android:right="5dp" android:left="5dp">
<shape android:shape="rectangle">
<solid android:color="#800000" />
</shape>
</item>
</layer-list>
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);
switch (e.Action)
{
case MotionEventActions.Down:
mstate = state.pressed;
this.Invalidate();
break;
case MotionEventActions.HoverEnter:
mstate = state.hovered;
this.Invalidate();
break;
case MotionEventActions.Up:
mstate = state.normal;
this.Invalidate();
break;
case MotionEventActions.HoverExit:
mstate = state.normal;
this.Invalidate();
break;
}
return (test);
}
private state mstate = state.normal;
private enum state
{
normal,
pressed,
hovered
}
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;
switch (mstate)
{
case state.normal:
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);
break;
case state.hovered:
//TODO:
break;
case state.pressed:
//TODO:
break;
}
}