Android 自定义布局 - onDraw() 永远不会被调用

标签 android layout view viewgroup

public class MainActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TableView tv = new TableView(this);
        tv.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
        setContentView(tv);      
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
}

public class TableView extends ViewGroup {
    private Paint oval;
    private RectF rect;

    public TableView(Context context) {
        super(context);
        oval= new Paint(Paint.ANTI_ALIAS_FLAG);
        oval.setColor(Color.GREEN);
    }


    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawOval(rect , oval);
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int wspec = MeasureSpec.makeMeasureSpec(
                getMeasuredWidth(), MeasureSpec.EXACTLY);
        int hspec = MeasureSpec.makeMeasureSpec(
                getMeasuredHeight(), MeasureSpec.EXACTLY);
        for(int i=0; i<getChildCount(); i++){
            View v = getChildAt(i);
            v.measure(wspec, hspec);
        }
    }


    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        float w=r-l;
        float h=b-t;
        rect=new RectF(w/8,h/8,7*w/8,7*h/8);
        float theta = (float) (2 * Math.PI / getChildCount());
        for(int i=0; i< getChildCount(); i++) {
            View v = getChildAt(i);
            w = (rect.right-rect.left)/2;
            h = (rect.bottom-rect.top)/2;
            float half = Math.max(w, h)/2;
            float centerX = rect.centerX()+w*FloatMath.cos(theta);
            float centerY = rect.centerY()+h*FloatMath.sin(theta);
            v.layout((int)(centerX-half),(int)(centerY-half),(int)(centerX+half),(int)(centerY+half));
        }
    }
}

嗯,几乎没有好的和深入的教程,几乎没有任何关于如何正确进行自定义布局的数据,所以我试图弄清楚它是如何完成的,我试图实现的是一个绘制绿色椭圆的布局在屏幕的中心,我希望这个布局的每个子元素都围绕椭圆形布置。

你可以把那个椭圆形想象成一个扑克 table ,我希望这种布局的 child 坐在它周围。

这段代码目前发生的情况是我得到一个没有椭圆形的白色应用程序屏幕,所以我对其进行了调试,发现 onDraw 永远不会被调用...

3 个问题:

  1. 为什么没有调用 onDraw?
  2. sdk 警告我不应该在 onLayout 方法中分配新对象,那么我应该在哪里计算 RectF 以便为 onDraw 调用做好准备?
  3. 调用 super.onDraw() 会让所有的 child 自己画吗?还是我应该明确调用他们的 draw()?

如果我完全错了,你们可以指导我朝着正确的方向前进,或者有任何与该主题相关的示例或教程的链接也会有所帮助!

最佳答案

默认情况下,onDraw() 不会为 ViewGroup 对象调用。相反,您可以覆盖 dispatchDraw()

或者,您可以通过在 TableView 构造函数中调用 setWillNotDraw(false) 来启用 ViewGroup 绘图。

编辑:

对于#2: - 在构造函数中初始化它,然后在你的 onLayout() 方法中调用 rect.set()

对于#3: - 是的,据我所知, super 调用会处理它,除非您需要自定义绘制 child 的方式,否则您不必处理它。

关于Android 自定义布局 - onDraw() 永远不会被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13056331/

相关文章:

java - 将 PCM 录制的数据写入 .wav 文件(java android)

java - 试图将 Activity 转换为 fragment

ruby-on-rails - 是否可以以编程方式清除 Rails 3 布局和 View 缓存?

css - Box-Sizing 似乎并没有像我期望的那样尊重填充

android - 当 clickable 为 false 时更改 Button 的背景颜色

jsf - JSF View 实例 : new view, 初始 View 和回发 View 之间的差异

android - 如何在Ubuntu中自动升级android studio

android - 使用存储在数据库中的路径显示 imageview

android - 以编程方式创建布局首选项

javascript - 在应用程序启动时将所有选项卡加载到 DOM 中(使用 Ionic)