控件完成绘制事件咨询及calendar control加载延迟显示spinner方法问询
嘿,我来帮你拆解这两个问题的解决方案:
问题1:控件完成绘制时的触发事件
不同平台下,监听控件绘制完成的方式略有不同,给你整理了主流平台的常用方案:
- Android平台:
- 可以通过
ViewTreeObserver的OnDrawListener监听每次绘制完成的时机;如果只需要监听首次绘制,OnGlobalLayoutListener更合适——它会在视图布局完成(此时绘制也基本完成)时触发。另外自定义控件时,重写onPostDraw()方法也能拿到绘制完成的信号,这个方法会在onDraw()执行完毕后立刻调用。
- 可以通过
- WPF/.NET平台:
Loaded事件是最常用的,它会在控件被加载到可视化树并完成首次绘制后触发;如果需要更精准的绘制结束时机,可以监听Rendered事件,或者用Dispatcher.BeginInvoke把后续逻辑放到UI线程的空闲队列,确保绘制完成后再执行。
- WinForms平台:
Paint事件会在每次重绘时触发,能捕捉绘制开始的时机;如果要确认首次绘制完成,结合HandleCreated事件加短延迟(比如用Timer)是比较可靠的方式,也可以通过Control.DrawToBitmap()间接判断控件是否已完成绘制。
问题2:创建Calendar Control延迟期间显示Spinner
核心思路是先展示Spinner占据界面,等Calendar初始化并完成绘制后,再替换成Calendar并隐藏Spinner,具体实现分平台举个例子:
Android示例
先在布局里同时放Spinner(用ProgressBar)和CalendarView,默认CalendarView隐藏:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ProgressBar android:id="@+id/loading_spinner" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true"/> <CalendarView android:id="@+id/calendar_view" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone"/> </RelativeLayout>
然后在代码里处理初始化和显示逻辑:
ProgressBar loadingSpinner = findViewById(R.id.loading_spinner); CalendarView calendarView = findViewById(R.id.calendar_view); // 先展示Spinner loadingSpinner.setVisibility(View.VISIBLE); // 把耗时的Calendar初始化放到后台线程,避免阻塞UI new Thread(() -> { // 模拟初始化耗时操作(比如加载数据、配置Calendar参数) try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } // 切回主线程更新UI runOnUiThread(() -> { calendarView.setVisibility(View.VISIBLE); // 监听Calendar绘制完成事件,确保完全显示后再隐藏Spinner calendarView.getViewTreeObserver().addOnDrawListener(new ViewTreeObserver.OnDrawListener() { @Override public void onDraw() { loadingSpinner.setVisibility(View.GONE); // 移除监听,防止重复触发 calendarView.getViewTreeObserver().removeOnDrawListener(this); } }); }); }).start();
WPF示例
XAML布局:
<Grid> <ProgressBar x:Name="LoadingSpinner" IsIndeterminate="True" VerticalAlignment="Center" HorizontalAlignment="Center"/> <Calendar x:Name="MyCalendar" Visibility="Collapsed"/> </Grid>
后台代码:
LoadingSpinner.Visibility = Visibility.Visible; // 用Task.Run处理耗时初始化,不阻塞UI Task.Run(() => { // 模拟耗时的Calendar配置操作 Thread.Sleep(1000); }).ContinueWith(task => { // 切回UI线程更新视图 Dispatcher.Invoke(() => { MyCalendar.Visibility = Visibility.Visible; // 监听Loaded事件,确认Calendar绘制完成后隐藏Spinner MyCalendar.Loaded += (s, e) => { LoadingSpinner.Visibility = Visibility.Collapsed; }; }); });
简单来说,就是用Spinner填补Calendar加载的空白期,通过绘制/加载完成事件确保时机准确,避免用户看到长时间的空白界面。
内容的提问来源于stack exchange,提问作者Ian Warburton
相关产品推荐
相关产品推荐

