2016-09-05 3 views
1

Я пытаюсь добавить два вида с холстами в свою деятельность программно, но похоже, что добавляется только первый (я могу сказать, посмотрев на вывод консоли). Что я делаю не так?Android добавляет два вида с холстами программным способом

Вот мой код:

package app.com.example.android.drawtwoviews; 

import android.content.Context; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.LinearLayout; 

public class MainActivity extends AppCompatActivity { 
    DrawView drawView; 
    DrawView2 drawView2; 
    private LinearLayout root; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     root = new LinearLayout(this); 
     root.setOrientation(LinearLayout.VERTICAL); 

     drawView = new DrawView(this); 
     drawView.setBackgroundColor(Color.WHITE); 
     root.addView(drawView); 

     drawView2 = new DrawView2(this); 
     drawView2.setBackgroundColor(Color.WHITE); 
     root.addView(drawView2); 

     setContentView(root); 
    } 

    public class DrawView extends View { 
     Paint paint = new Paint(); 

     public DrawView(Context context) { 
      super(context); 
     } 

     @Override 
     public void onDraw(Canvas canvas) { 
      System.out.println("DrawView1"); 
      paint.setColor(Color.BLACK); 
      //paint.setStrokeWidth(3); 
      canvas.drawRect(30, 30, 80, 80, paint); 


     } 

    } 


    public class DrawView2 extends View { 
     Paint paint = new Paint(); 

     public DrawView2(Context context) { 
      super(context); 
     } 

     @Override 
     public void onDraw(Canvas canvas) { 
      System.out.println("DrawView2"); 
      paint.setColor(Color.BLUE); 
      paint.setStrokeWidth(3); 
      canvas.drawRect(300, 300, 400, 400, paint); 


     } 

    } 
} 

ответ

2

Вы добавляете свои виды на root без указания параметров макета. Это означает, что они оба получают default layout parameters of LinearLayout, который для вертикальной компоновки составляет (MATCH_PARENT, WRAP_CONTENT).

Ни один из ваших пользовательских видов не переопределяет onMeasure(), что означает как measure, так и их минимальный размер по умолчанию 0 × 0.

Это означает, что ваш LinearLayout отображает два вида с запрошенным размером 0 × 0 и спецификацией макета (MATCH_PARENT, WRAP_CONTENT). Способ, которым это работает, - a bit tricky, но ваш первый ребенок занимает высоту всего экрана, а ваш второй ребенок равен 0px. Оба ребенка имеют полную ширину экрана. Вы можете легко увидеть это в Hierarchy Viewer.

Чтобы устранить эту проблему, необходимо либо указать макет Params:

// in onCreate() 
int width = LinearLayout.LayoutParams.MATCH_PARENT; 
int height = 0; 
int weight = 1; 
LinearLayout.LayoutParams params = 
    new LinearLayout.LayoutParams(width, height, weight); 

drawView = new DrawView(this); 
drawView.setBackgroundColor(Color.WHITE); 
root.addView(drawView, params); // note the extra argument 

drawView2 = new DrawView2(this); 
drawView2.setBackgroundColor(Color.WHITE); 
root.addView(drawView2, params); // note the extra argument 

Или вы можете изменить DrawView S так, что они измеряют до некоторого минимального размера:

public class DrawView extends View { 
    // paint 
    // constructor 
    // onDraw 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
    { 
     setMeasuredDimension(80, 80); 
    } 
} 


public class DrawView2 extends View { 
    // paint 
    // constructor 
    // onDraw 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
    { 
     setMeasuredDimension(400, 400); 
    } 
} 
+0

Это отлично работает! Я хотел бы удостовериться, что, когда я установил параметр height (of LayoutParams) равным 0, я фактически устанавливаю высоту до минимума, который займет холст. – Naci

+1

Настройка 0 для 'LayoutParams.height' работает только потому, что есть _also_' LayoutParams.weight'. Высота 0 - это способ сказать «идти только по макету». Если вы хотите иметь минимальный размер в DrawViews, вы должны добавить реализацию onMeasure(), чтобы LinearLayout мог получить свой минимальный размер, используйте 'height = LayoutParams.WRAP_CONTENT' в одном LayoutParams DrawView и' height = 0, weight = 1' на другой DrawViewParams DrawView. – Barend

0

Попробуйте установить этот флаг в вашем дизайне вашего вида:

public DrawView(Context context) { 
     super(context); 
     setWillNotDraw(false); 
} 

Это необходимо, потому что ваш взгляд не знает, что вы хотите сделать пользовательский чертеж, и onDraw() никогда не вызывается, так как рисовать нечего.

Смежные вопросы