web-dev-qa-db-fra.com

Android Disposition personnalisée - onDraw () n'est jamais appelé

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

Eh bien, il n'y a presque AUCUN bon et profond tutoriels et presque aucune donnée sur la façon de faire des mises en page personnalisées correctement, alors j'ai essayé de comprendre comment c'est fait, ce que j'essaie d'implémenter est une mise en page qui peint un ovale vert au centre de l'écran, et je veux que chaque enfant de cette disposition soit disposé autour de l'ovale.

vous pouvez considérer cet ovale comme une table de poker que je veux que les enfants de cette disposition s'assoient autour d'elle.

Ce qui se passe actuellement avec ce code, c'est que j'obtiens un scren d'application blanc sans ovale, donc je l'ai débogué et j'ai vu qu'onDraw n'était jamais appelé ...

3 questions:

  1. pourquoi onDraw n'est-il pas appelé?
  2. le sdk m'avertit que je ne devrais pas allouer de nouveaux objets dans la méthode onLayout, alors où dois-je calculer le RectF pour qu'il soit prêt pour l'appel onDraw à venir?
  3. l'appel de super.onDraw () inciterait-il tous les enfants à se peindre? ou devrais-je invoquer explicitement leur draw ()?

Si je me trompe et que vous pouvez me guider dans la bonne direction, ou avoir des liens vers des exemples ou des didacticiels liés à ce sujet, cela serait utile aussi!

45
Ofek Ron

Par défaut, onDraw() n'est pas appelé pour les objets ViewGroup. Au lieu de cela, vous pouvez remplacer dispatchDraw().

Alternativement, vous pouvez activer le dessin ViewGroup en appelant setWillNotDraw(false) dans votre constructeur TableView.

ÉDITER:

Pour # 2: - Initialisez-le dans le constructeur, puis appelez simplement rect.set() dans votre méthode onLayout().

Pour # 3: - Oui, pour autant que je sache, le super appel le gérera, vous ne devriez pas avoir à gérer cela sauf si vous devez personnaliser la façon dont les enfants sont dessinés.

140
kcoppock