我们目前正在使用 Xamarin 构建一个应用程序,我们希望在其中可视化与中性值的偏差水平。当前状态将每 80 到 150 毫秒更新一次。
基本上我们正在寻找这样的东西:
---- ´´´´´ ----(偏差为正)
---- ----- ----(无偏差)
---- ___ ----(负偏差)
外侧的线将保持在同一位置,而中间的线上下移动以显示当前偏差。
对于 WP,它就像在一条线上绘制 3 个细长的矩形并通过 Rectangle.RenderTransform 将 Y 轴上的值转换到中间的矩形一样简单。
在 Android 中,我们使用 LevelListDrawable 将几个 png 绑定(bind)到某个值范围,并通过代码设置当前级别: 这是 LevelList.xml:
<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:drawable="@drawable/down"
android:minLevel="0"
android:maxLevel="33" />
<item
android:drawable="@drawable/neutral"
android:minLevel="34"
android:maxLevel="66" />
<item
android:drawable="@drawable/top"
android:minLevel="67"
android:maxLevel="100" />
</level-list>
down、neutral 和 top 指的是显示当前状态的 .png。 (将有大约 20 个不同的状态)
LevelList.xml 为用于显示当前状态的 ImageView 设置为 ImageDrawable:
_graphicsView = FindViewById<ImageView>(Resource.Id.GraphicsView);
var drawable = Resources.GetDrawable(Resource.Drawable.LevelList);
_graphicsView.SetImageDrawable(drawable);
这是 MainActivity 中的更新方法:
public void UpdateDeviation(int deviation)
{
_graphicsView.SetImageLevel(deviation);
}
我们目前的方法很有效,但我们对必须为每个州存储大量 png 感到不高兴。关于更新速度和 APK 大小,您能想到更好的 Android 解决方案吗?
最佳答案
您绝对可以通过实现自己的 SurfaceView 来改善这一点并根据不同的状态渲染路径。
无聊所以写了个例子:
代码:
public enum LineState
{
Up, Middle, Down,
}
public class OscillatingSurface : SurfaceView
{
public LineState _state = LineState.Middle;
private readonly Paint _paint;
public OscillatingSurface (Context context)
: base(context)
{
_paint = new Paint(PaintFlags.AntiAlias);
_paint.SetStyle (Paint.Style.Stroke);
_paint.Color = Color.White;
_paint.StrokeWidth = 10.0f;
}
public void SetState(LineState state)
{
this._state = state;
float factor = 0.5f;
if (_state == LineState.Up) {
factor = 0.6f;
} else if (state == LineState.Down) {
factor = 0.4f;
}
float width = (float)this.Width;
float height = (float)this.Height;
Path path = new Path();
path.MoveTo (0.0f, height * 0.5f); // Far left point.
path.LineTo (width * 0.25f, height * 0.5f); // Middle left point.
path.LineTo (width * 0.25f, height * factor); // Left Oscilation point
path.LineTo (width * 0.75f, height * factor); // Right oscilation point
path.LineTo (width * 0.75f, height * 0.5f); // Middle right point.
path.LineTo (width, height * 0.5f); // Far right point.
var canvas = this.Holder.LockCanvas (); // Acquire surface.
canvas.DrawColor (Color.Black); // Clear surface.
canvas.DrawPath (path, _paint); // Render the path.
Holder.UnlockCanvasAndPost (canvas); // Release and render!
}
}
[Activity (Label = "Oscillating Surface", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
OscillatingSurface surface;
Oscillator oscillator;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
surface = new OscillatingSurface (this);
oscillator = new Oscillator (this, surface, 1000);
SetContentView (surface);
}
protected override void OnResume ()
{
oscillator.Start ();
base.OnResume ();
}
}
public class Oscillator
{
int _frequency;
OscillatingSurface _surface;
Activity _owner;
public Oscillator(Activity owner, OscillatingSurface surface, int frequency)
{
_surface = surface;
_frequency = frequency;
_owner = owner;
}
public void Start()
{
System.Threading.Tasks.Task.Run (() => {
while (true) {
LineState next = (LineState)((((int)_surface._state) + 1) % 3);
_owner.RunOnUiThread( () => {
_surface.SetState(next);
});
Thread.Sleep(_frequency);
}
});
}
}
它的作用:
你只需要注意上面代码中的OscillatingSurface
类;其他一切只是举例。
资源:
关于android - 寻找等效于 UIElement.RenderTransform 以可视化 Android 中的偏差级别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27150350/