自定义View调用onDraw方法

luqing414 2014-09-16 12:13:24
我现在有一个需求,要自定义View,初始化的时候调用了onDraw方法,完后我自定义一个方法,调用该方法的时候,要重新调用onDraw方法,但我用postInvalidate无效,代码如下:

启动类:

public class MainActivity extends Activity {
TestOnDraw view;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

view = (TestOnDraw) findViewById(R.id.test);

new Thread(new Runnable() {

@Override
public void run() {
view.test();
}
}).start();
}
}


布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>

<com.example.testdraw.TestOnDraw
android:id="@+id/test"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>

</LinearLayout>


自定义View

public class TestOnDraw extends View {

public TestOnDraw(Context context) {
this(context, null);
}

public TestOnDraw(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public TestOnDraw(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}

@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);

Log.d("test", "in");
}

public void test() {
postInvalidate();
}
}


我查看日志,onDraw方法只进了一次,就是说postInvalidate();没有生效,我如何修改能实现在初始化进入onDraw后,调用test方法时再次进入onDraw方法
...全文
1605 13 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
009茜茜 2017-01-24
  • 打赏
  • 举报
回复
你的第一个构造函数加上super(context);试试
chanchan0010 2015-07-30
  • 打赏
  • 举报
回复
这个可能是界面内容没有任何变化导致的,你可以在线程中试着改变一下界面的内容。
Kobe-Bean-Bryant 2015-04-12
  • 打赏
  • 举报
回复
我也碰到了这样的问题,不知道调用Invalidate()或postInvalidate() 都无法调用onDraw(),导致无法更新,求救...
Bob_yang912 2014-11-05
  • 打赏
  • 举报
回复
你好 能问下关于这个帖子提到的问题么
老科达 2014-09-17
  • 打赏
  • 举报
回复
引用 6 楼 luqing414 的回复:
[quote=引用 5 楼 lionfresh 的回复:] 我觉得在view = (TestOnDraw) findViewById(R.id.test)时onDraw并不是延迟执行了,而是根本就没有执行。
执行了,我说清空test方法就是将test方法弄成空实现,里面一行代码都没有,完后可以看到onDraw还是调用了的[/quote] postInvalidate() 是往UI队列中丢一个线程,之后开始渲染流程。 在onCreate中 所有的界面并没有实际生成,所以会优先执行postInvalidate中的代码(这个在渲染队列前头)。 但是这个是没有效果的。 view 中有个skipInvalidate()方法 说的就是 当view未显示时候,是被skip掉的。 假如你delay了这个1-2秒, 这个代码执行时后界面已经生成了,他的invalidate就生效, 就会出现你想要的执行两次。 另 界面生成时候,必然会调用一次onDraw。 /** * Invalidate the whole view. If the view is visible, * {@link #onDraw(android.graphics.Canvas)} will be called at some point in * the future. This must be called from a UI thread. To call from a non-UI thread, * call {@link #postInvalidate()}. */ public void invalidate() { invalidate(true); } public void invalidate(Rect dirty) { if (skipInvalidate()) { return; } } }
lionfresh 2014-09-16
  • 打赏
  • 举报
回复
你不在子线程中操作,并将postInvalidate()改为invalidate(),运行看能不能刷新呢
Kifile 2014-09-16
  • 打赏
  • 举报
回复
引用 7 楼 luqing414 的回复:
[quote=引用 3 楼 kifile 的回复:] onDraw()的方法是当在屏幕中需要显示界面的时候才调用的,android会判断某个界面是否需要绘制,如果不需要就根本不会调用到他的onDraw 方法, 例如你把你的自定义view设置为GONE,那么你根本看不到打出来的log了 另外,为什幺要调用postInviliade呢, Java 的动态绑定机制不是会默认调用子类的onDraw方法吗? 你在线程中再调取一次postInvliade有什么意义吗?
我是程序要不断的去改变这个自定义View的显示形状,所以要不断的重绘,我这里为了让问题清楚没有将其他逻辑包含进来[/quote] ..那就在 onDraw() 里调用invaliade,另外建议使用Surface View 实现,避免阻塞线程
luqing414 2014-09-16
  • 打赏
  • 举报
回复
引用 3 楼 kifile 的回复:
onDraw()的方法是当在屏幕中需要显示界面的时候才调用的,android会判断某个界面是否需要绘制,如果不需要就根本不会调用到他的onDraw 方法, 例如你把你的自定义view设置为GONE,那么你根本看不到打出来的log了 另外,为什幺要调用postInviliade呢, Java 的动态绑定机制不是会默认调用子类的onDraw方法吗? 你在线程中再调取一次postInvliade有什么意义吗?
我是程序要不断的去改变这个自定义View的显示形状,所以要不断的重绘,我这里为了让问题清楚没有将其他逻辑包含进来
luqing414 2014-09-16
  • 打赏
  • 举报
回复
引用 5 楼 lionfresh 的回复:
我觉得在view = (TestOnDraw) findViewById(R.id.test)时onDraw并不是延迟执行了,而是根本就没有执行。
执行了,我说清空test方法就是将test方法弄成空实现,里面一行代码都没有,完后可以看到onDraw还是调用了的
lionfresh 2014-09-16
  • 打赏
  • 举报
回复
我觉得在view = (TestOnDraw) findViewById(R.id.test)时onDraw并不是延迟执行了,而是根本就没有执行。
lionfresh 2014-09-16
  • 打赏
  • 举报
回复
引用 2 楼 luqing414 的回复:
[quote=引用 1 楼 lionfresh 的回复:] 你不在子线程中操作,并将postInvalidate()改为invalidate(),运行看能不能刷新呢
不行,试过,我解决了,我用handler延时1秒后再在handleMessage里面去执行test方法就可以了,就我现在看到的情况来看,view = (TestOnDraw) findViewById(R.id.test);这句话并不会马上调用onDraw,test方法中加日志可以看到是先进了test方法后才调用onDraw,而且这时test中的postInvalidate方法也没起作用(将test方法清空,可以看到也进了一次onDraw方法,证实跟postInvalidate无关),所以我总结应该是onDraw方法不会在初始化自定义控件后马上调用[/quote] 你说的将将test方法清空是什么意思呢?
Kifile 2014-09-16
  • 打赏
  • 举报
回复
onDraw()的方法是当在屏幕中需要显示界面的时候才调用的,android会判断某个界面是否需要绘制,如果不需要就根本不会调用到他的onDraw 方法, 例如你把你的自定义view设置为GONE,那么你根本看不到打出来的log了 另外,为什幺要调用postInviliade呢, Java 的动态绑定机制不是会默认调用子类的onDraw方法吗? 你在线程中再调取一次postInvliade有什么意义吗?
luqing414 2014-09-16
  • 打赏
  • 举报
回复
引用 1 楼 lionfresh 的回复:
你不在子线程中操作,并将postInvalidate()改为invalidate(),运行看能不能刷新呢
不行,试过,我解决了,我用handler延时1秒后再在handleMessage里面去执行test方法就可以了,就我现在看到的情况来看,view = (TestOnDraw) findViewById(R.id.test);这句话并不会马上调用onDraw,test方法中加日志可以看到是先进了test方法后才调用onDraw,而且这时test中的postInvalidate方法也没起作用(将test方法清空,可以看到也进了一次onDraw方法,证实跟postInvalidate无关),所以我总结应该是onDraw方法不会在初始化自定义控件后马上调用

80,471

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧