android - 寻找等效于 UIElement.RenderTransform 以可视化 Android 中的偏差级别

标签 android animation graphics xamarin

我们目前正在使用 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);
            }
        });
    }
}

它的作用:

enter image description here enter image description here enter image description here

你只需要注意上面代码中的OscillatingSurface类;其他一切只是举例。

资源:

关于android - 寻找等效于 UIElement.RenderTransform 以可视化 Android 中的偏差级别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27150350/

相关文章:

JavaFX GraphicsContext 倒圆

C# 在 Windows 中重新排列多显示位置

android - 使用功能的分层逻辑?

c# - 在 Google Play 控制台中分析或收集 ANR 的 Xamarin 堆栈跟踪

python - Matplotlib error Line2d object s not iterable error in tkinter callback nothing shows up

android - 添加 fragment 时从汉堡包到箭头图标的过渡动画

c++ - GLFW 无响应全屏窗口

android - 如果打开,隐藏 Android 软键盘

java - 在没有对象映射器的情况下将对象转换为 Jackson 中的 JSON 文件

c# - 动画 RenderTransformOrigin