在Flutter中延迟重绘窗口小部件

时间:2019-05-22 12:17:10

标签: android dart flutter

我想基于条件逻辑从窗口小部件中删除内容。

下面是我的小部件树,

return MaterialApp(
    home: Scaffold(
    body: Container(
    margin: EdgeInsets.all(120.0),
    child: Align(
      alignment: Alignment.center,
      child: Column(
        children: <Widget>[
          Text("Loading...");
        ],
      ),
    ),
  ),
));

让我们说我有一个变量,该变量从SharePreferences中获取值,如果值是“ Hide”,则必须隐藏封装在其中的Text小部件。否则,它将显示从SP提取的文本。

这里要注意的是,文本最初将在特定时间段内显示“正在加载...”,然后必须根据条件动态地运行。

我尝试使用TimersetState(),但无法真正使其正常工作。如果有人对此有解决方案,请提供帮助。

2 个答案:

答案 0 :(得分:1)

乔丹·戴维斯是对的。您需要 public class PieView : View { int w, h, pl, pr, pt, pb, usableWidth, usableHeight, radius, cx, cy, lineLenght; Paint paint; public Canvas canvas; public float firstLineangle = 0; public float secondLineangle = 40; public float thirdLineangle = 120; float currentAngle,maxAngle; public override void Draw(Canvas canvas) { base.Draw(canvas); w = Width; h = Height; pl = PaddingLeft; pr = PaddingRight; pt = PaddingTop; pb = PaddingBottom; this.canvas = canvas; usableWidth = w - (pl + pr); usableHeight = h - (pt + pb); radius = Math.Min(usableWidth, usableHeight) / 2; cx = pl + (usableWidth / 2); cy = pt + (usableHeight / 2); lineLenght = radius - (pl * 2) - (pr * 2); paint = new Paint(); paint.Color = Android.Graphics.Color.White; paint.SetStyle(Paint.Style.Stroke); paint.StrokeWidth = 5; canvas.DrawCircle(cx, cy, radius - 5, paint); Drawline(canvas, firstLineangle); Drawline(canvas, secondLineangle); Drawline(canvas, thirdLineangle); PostInvalidateDelayed(500); Invalidate(); } public void Drawline(Canvas canvas, float angle) { float displacedAngle = angle - 90; float x = cx + ((float)Math.Cos(degreesToRadians(displacedAngle)) * (radius - 5)); //convert angle to radians for x and y coordinates float y = cy + ((float)Math.Sin(degreesToRadians(displacedAngle)) * (radius - 5)); canvas.DrawLine(cx, cy, x, y, paint); //draw a line from center point back to the point } public double degreesToRadians(double degrees) { return (degrees * Math.PI) / 180; } } public class PieAnimation : Android.Views.Animations.Animation { private PieView pieView; private float firstLineangle; private float secondLineangle; private float thirdLineangle; public PieAnimation(PieView pieView, float firstLineangle,float secondLineangle,float thirdLineangle) { this.pieView = pieView; this.firstLineangle = firstLineangle; this.secondLineangle = secondLineangle; this.thirdLineangle = thirdLineangle; } protected override void ApplyTransformation(float interpolatedTime, Transformation t) { pieView.firstLineangle = 0 + ((firstLineangle) * interpolatedTime); pieView.secondLineangle = 0 + ((secondLineangle) * interpolatedTime); pieView.thirdLineangle = 0 + ((thirdLineangle) * interpolatedTime); pieView.RequestLayout(); } } public class TourPager : Java.Lang.Object, ViewPager.IOnPageChangeListener, ViewPager.IPageTransformer { private ViewPager mViewPager; private float mLastOffset; public TourView _context; public TourPager(ViewPager viewpager, TourView context) { mViewPager = viewpager; viewpager.AddOnPageChangeListener(this); _context = context; } public void OnPageSelected(int position) { if (position == 0) { PieAnimation animation = new PieAnimation(_context._pieView, 0, 40, 120); animation.Duration = (1000); _context._pieView.StartAnimation(animation); } if (position==1) { PieAnimation animation = new PieAnimation(_context._pieView, 100, 140, 200); animation.Duration=(1000); _context._pieView.StartAnimation(animation); } if(position==2) { PieAnimation animation = new PieAnimation(_context._pieView, 180, 270, 10); animation.Duration = (1000); _context._pieView.StartAnimation(animation); } } FutureBuilder

StreamBuilder

只需将return MaterialApp( home: Scaffold( body: Container( margin: EdgeInsets.all(120.0), child: Center( child: FutureBuilder( future: Future.delayed(Duration(seconds: 3)), builder: (c, s) => s.connectionState == ConnectionState.done ? Text("Loaded") : Text("Loading..."))), ), )); 替换为您的函数即可。

答案 1 :(得分:0)

我终于找到了将@ olexa.le的Future.Delayed方法与一些修改结合起来的解决方案。

 main() {
    runApp(MyPrimaryWidgetBuilder());

    Future.delayed(const Duration(seconds: 5), () async {
    SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
    String appRunStatus = sharedPreferences.getString("appStartStatus");

    if( appRunStatus == null || appRunStatus == "" ){
        //Redraw new Widget
    }
}

现在,由于main()中设置的延迟,我的初始Widget将被绘制到视口,然后Future方法将等待5秒。然后,条件块将检查sharedPreferences.getString()

返回的值

如果该值为NULL,那么我的目标是绘制一个新的小部件来替换现有的小部件。在条件模块中,我只是使用新的小部件再次调用runApp()方法。

if( appRunStatus == null || appRunStatus == "" ){
      runApp(
         new MaterialApp(
             home: Scaffold(
                 body: Container(
                    child: Text("You Are running the app for the first time..."),
                 ),
             ),
      );
}

假设,最初显示的布局将包含文本 “正在加载...” ,并且该文本将保持5秒钟。 5秒钟后根据返回的值 SharePreferences,整个应用程序的视图将使用新的小部件重新绘制。

我重新绘制了大约6个新的小部件,并且还包含了一些适合我的用例的动画。 Text小部件只是一个示例,您可以将其替换为所需的任何名称,这将起作用。它将适合在不导航到新页面的情况下使用新的子项重新绘制窗口小部件。

这对我有用,如果有更好的解决方案可以更高效地实现相同目标,请分享一下。