2013-11-28 8 views
5

ich eine benutzerdefinierte Ansicht und fügte hinzu, es zu Layout:Wie erkenne ich das Eltern-Padding aus der benutzerdefinierten Ansicht?

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
     xmlns:tools="http://schemas.android.com/tools" 
     xmlns:custom="http://schemas.android.com/apk/res/com.eleks.customview" 
     android:padding="20dp" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" > 

     <com.eleks.customview.CView 
      android:id="@+id/circle1" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      custom:textSize="@dimen/circle_text_size" 
      custom:text="@string/circle_default_text" 
      custom:radius="@dimen/circle_radius" 
      custom:textColor="@color/circle_text" 
      custom:textBackground="@color/circle_background" /> 

    </LinearLayout> 

I onMeasure in benutzerdefinierter Ansicht und setzen Sie Breite und Höhe implementieren. Aber meine Ansicht ignoriert Eltern-Padding (20dp). Sehen Sie das Bild:

enter image description here

public class CView erstreckt Ansicht { private static final String TAG = "CView";

// default value 
private static final int DEFAULT_RADIUS = 30; 
private static final int DEFAULT_TEXT_SIZE = 12; 
private static final int DEFAULT_TEXT_COLOR = Color.BLACK; 
private static final int DEFAULT_BACKGROUND = Color.GRAY; 
private static final int DEFAULT_WIDTH = DEFAULT_RADIUS * 2; 
private static final int DEFAULT_HEIGHT = DEFAULT_RADIUS * 2; 

// variables 
private Paint mBackgroundPaint = null; 
private Paint mTextPaint = null; 
private float mCircleX = 0; 
private float mCircleY = 0; 
private float mTextX = 0; 
private float mTextY = 0; 
private int mWidth = DEFAULT_WIDTH; 
private int mHeight = DEFAULT_HEIGHT; 

// attrs 
private int mTextColor = DEFAULT_TEXT_COLOR; 
private int mBackground = DEFAULT_BACKGROUND; 
private float mRadius = DEFAULT_RADIUS; 
private String mText = null; 
private float mTextSize = 0; 

public CView(Context context) 
{ 
    super(context); 
    Log.d(TAG, "init view"); 
    init(null); 
} 

public CView(Context context, AttributeSet attrs) 
{ 
    super(context, attrs); 
    Log.d(TAG, "init view"); 
    init(attrs); 
} 

private void init(AttributeSet attrs) 
{ 
    if (attrs != null) 
    { 
     TypedArray a = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.CircleButton, 0, 0); 
     try 
     { 
      mTextColor = a.getColor(R.styleable.CircleButton_textColor, DEFAULT_TEXT_COLOR); 
      mBackground = a.getColor(R.styleable.CircleButton_textBackground, DEFAULT_BACKGROUND); 
      mRadius = a.getDimension(R.styleable.CircleButton_radius, DEFAULT_RADIUS); 
      mText = a.getString(R.styleable.CircleButton_text); 
      mTextSize = a.getDimensionPixelOffset(R.styleable.CircleButton_textSize, DEFAULT_TEXT_SIZE); 
     } 
     finally 
     { 
      a.recycle(); 
     } 
    } 
    mBackgroundPaint = new Paint(); 
    mBackgroundPaint.setColor(mBackground); 

    this.setMinimumHeight((int) mRadius * 2); 
    this.setMinimumWidth((int) mRadius * 2); 
} 

private void initLayoutParams() 
{ 
    LayoutParams params = this.getLayoutParams(); 
    params.width = mWidth + getLeft(); 
    params.height = mHeight + getTop(); 
    Log.d(TAG, "params| width: " + mWidth + " height: " + mHeight); 
} 

private void initText() 
{ 
    mTextPaint = new Paint(); 
    mTextPaint.setColor(mTextColor); 
    mTextPaint.setTextSize(mTextSize); 
    Rect textRect = new Rect(); 
    if (mText == null) 
    { 
     mText = ""; 
    } 
    mTextPaint.getTextBounds(mText, 0, mText.length(), textRect); 
    mTextX = mCircleX - (((Math.abs(textRect.right) - Math.abs(textRect.left)))/2); 
    mTextY = mRadius + ((Math.abs(textRect.top) - (Math.abs(textRect.bottom)))/2); 
    Log.d(TAG, "text| x: " + mTextX + " y: " + mTextY); 
} 

@Override 
protected void onDraw(Canvas canvas) 
{ 
    super.onDraw(canvas); 
    Log.d(TAG, "init onDraw"); 

    if (canvas != null) 
    { 
     canvas.drawCircle(mCircleX, mCircleY, mRadius, mBackgroundPaint); 
     // canvas.drawText(mText, mTextX, mTextY, mTextPaint); 
    } 
} 

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
{ 
    // super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
    Log.d(TAG, "init onMeasure"); 
    setWidth(MeasureSpec.getMode(widthMeasureSpec), MeasureSpec.getSize(widthMeasureSpec)); 
    setHeight(MeasureSpec.getMode(heightMeasureSpec), MeasureSpec.getSize(heightMeasureSpec)); 
    mCircleX = getLeft() - getPaddingLeft() + mRadius; 
    mCircleY = getTop() - getPaddingTop() + mRadius; 
    fixedSize(); 
    Log.d(TAG, "circle| x: " + mCircleX + " y: " + mCircleY); 
    this.setMeasuredDimension(mWidth, mHeight); 
    // initText(); 

} 

private void fixedSize() 
{ 
    if (mWidth > mHeight) 
    { 
     mHeight = mWidth; 
    } 
    else if (mHeight > mWidth) 
    { 
     mWidth = mHeight; 
    } 
} 

private void setWidth(final int modeWidth, final int width) 
{ 
    switch (modeWidth) 
    { 
     case MeasureSpec.AT_MOST: 
      Log.d(TAG, "width mode is AT_MOST"); 
      if (mRadius > 0) 
      { 
       mWidth = (int) (mRadius * 2) + getPaddingLeft() + getPaddingRight(); 
      } 
      else 
      { 
       mWidth = DEFAULT_WIDTH; 
      } 
      mWidth = Math.min(mWidth, width); 
      break; 
     case MeasureSpec.EXACTLY: 
      Log.d(TAG, "width mode is EXACTLY"); 
      break; 
     case MeasureSpec.UNSPECIFIED: 
     default: 
      Log.d(TAG, "width mode is UNSPECIFIED"); 
      mWidth = DEFAULT_WIDTH; 
      break; 
    } 
} 

private void setHeight(final int modeHeight, final int height) 
{ 
    switch (modeHeight) 
    { 
     case MeasureSpec.AT_MOST: 
      Log.d(TAG, "height mode is AT_MOST"); 
      if (mRadius > 0) 
      { 
       mHeight = (int) (mRadius * 2) + getPaddingTop() + getPaddingBottom(); 
      } 
      else 
      { 
       mHeight = DEFAULT_HEIGHT; 
      } 
      mHeight = Math.min(mHeight, height); 
      break; 
     case MeasureSpec.EXACTLY: 
      Log.d(TAG, "height mode is EXACTLY"); 
      break; 
     case MeasureSpec.UNSPECIFIED: 
     default: 
      Log.d(TAG, "height mode is UNSPECIFIED"); 
      mHeight = DEFAULT_HEIGHT; 
      break; 
    } 
} 

@Override 
protected void onLayout(boolean changed, int left, int top, int right, int bottom) 
{ 
    // super.onLayout(changed, left, top, right, bottom); 
    Log.d(TAG, "init onLayout"); 
    initLayoutParams(); 
} 

Wie bekomme ich Eltern Padding?

+0

Wie würde die Polsterung des Elternteils Ihre Ansicht beeinflussen ??? – pskink

+0

Ja, das Padding der Eltern beeinflusst meine Ansicht. Es ist ein Problem. – Viacheslav

+0

Also ich denke, Sie sollten lesen Dokumentation lesen, Abschnitt "Größe, Polsterung und Rand" – pskink

Antwort

2

Verwendung getParent(), aber imho, wenn Sie es dort noch einige Designfehler

+0

Für @Viacheslav auf die Frage für die detaillierte Antwort zu überprüfen. – Irfan

+0

@Irfan was meinst du? Was Kommentar? – pskink

+0

in Kommentaren der Frage, es habe einige detaillierte Erklärung. Ich bin darauf hingewiesen. – Irfan

0

Die Polsterung der übergeordneten Ansicht von der Mutter gemessen wird. Du solltest es nicht berücksichtigen. Sie sollten jedoch Ihre benutzerdefinierte Widget-Polsterung berücksichtigen. Der Code funktioniert nicht, weil Ihre Maßeinheit nicht das tut, was sie tun soll. Ich habe den Rest des Codes nicht überprüft, aber wahrscheinlich hast du auch andere Fehler gemacht).

onMeasure() soll die Größe Ihrer Ansicht berechnen und in setMeasuredDimension() setzen.

Wenn Sie benutzerdefinierte Ansichten entwickeln möchten, sollten Sie die offizielle Dokumentation lesen. In diesem Fall die Methoden-Dokumentation onMeasure(int, int). Ich rate auch zu lesen über how Android draw views.

Und möglicherweise den Code eines Widget auf GitHub oder einige Standard-Android-Ansicht zu sehen, wie sie die Ansicht zu messen. (LinearLayout und RelativeLayout sind gut und sehr unterschiedlich, Beispiel für ViewGroups) während ImageView ein schönes vollständiges Beispiel für ein Widget ist.

Auch wenn Sie keine ViewGroup schreiben, ist es hilfreich zu verstehen, was sie von einer untergeordneten Ansicht erwartet. Die Idee ist, dass es (und ist oft) eine mehrstufige Passage sein kann, bei der der Elternteil versucht, das Kind in sich selbst zu passen, indem er verschiedene Zwänge übergibt.

Stellen Sie sich Folgendes vor: measureSpecs (die Parameter, die Sie erhalten) sagt Ihnen, ob Sie den gewünschten Platz einnehmen sollen, ob Sie in eine bestimmte Größe passen oder GENAU diese Größe, sowohl in Breite als auch Höhe. Ihr Widget sollte diesen Beschränkungen folgen und setMeasuredDimension() mit dem von Ihnen berechneten Maß aufrufen.

In Ihrem Fall sollte es 2 * radious + padding sein, es sei denn, dies ist mehr als der Platz von der übergeordneten Ansicht gegeben.

Das gesagt, wenn Sie einen Kreis zeichnen möchten, ist eine benutzerdefinierte Ansicht nicht wirklich der Weg zu gehen, aber ich denke, Sie haben nur versucht zu lernen, wie benutzerdefinierte Ansichten zu erstellen.

Verwandte Themen