Подтвердить что ты не робот

Пользовательский макет Android - onDraw() никогда не вызывается

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));
        }
    }
}

Ну, почти нет НИКАКИХ хороших и глубоких уроков, и вряд ли какая-либо часть данных о том, как делать пользовательские макеты, поэтому я попытался выяснить, как это делается, что я пытаюсь реализовать - это макет, который рисует зеленый овал в центре экрана, и я хочу, чтобы каждый ребенок этого макета был выложен вокруг овала.

вы можете думать о том, что овал как покерный стол, который я хочу, чтобы дети этого макета сидели вокруг него.

Что в настоящее время происходит с этим кодом, так это то, что я получаю белое приложение scren без овала, поэтому я его отладил и увидел, что onDraw никогда не вызывается...

3 вопроса:

  • Почему onDraw не получает вызов?
  • sdk предупреждает меня, что я не должен выделять новые объекты в методе onLayout, поэтому где я должен вычислять RectF, чтобы он был готов для вызова onDraw?
  • ли вызов super.onDraw() заставит всех детей рисовать себя? или я должен явно вызвать их draw()?

Если я все ошибаюсь, и вы, ребята, можете вести меня в правильном направлении или иметь какие-либо ссылки на примеры или учебники, связанные с этой темой, которые тоже будут полезны!

4b9b3361

Ответ 1

По умолчанию onDraw() не вызывается для объектов ViewGroup. Вместо этого вы можете переопределить dispatchDraw().

В качестве альтернативы вы можете включить рисование ViewGroup, вызвав setWillNotDraw(false) в свой конструктор TableView.

Смотрите: объяснение Ромена Гая

EDIT:

Для # 2: - Инициализируйте его в конструкторе, а затем просто вызовите rect.set() в свой метод onLayout().

За # 3: - Да, насколько мне известно, супер-вызов будет обрабатывать его, вам не придется обращаться с этим, если вам не нужно настраивать способ рисования детей.

Ответ 2

Если вы хотите, чтобы холст был повторно нарисован call invalidate(), и метод onDraw() будет перезаписан