measure all child views of RelativeView before drawing
Asked Answered
C

1

1

I have method, which should create a Bitmap from the RelativeLayout. My RelativeLayout creates dynamically and place all input Views into the circle. It looks like this:

public class CircleView extends RelativeLayout {
static final int centerId = 111;
private final int radius;
Bitmap returnedBitmap;
private RelativeLayout.LayoutParams createNewRelativeLayoutParams() {
          RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
                             RelativeLayout.LayoutParams.WRAP_CONTENT,
                             RelativeLayout.LayoutParams.WRAP_CONTENT);
          lp.addRule(RelativeLayout.ABOVE, centerId);
          lp.addRule(RIGHT_OF, centerId);
          return lp;
}

private View prepareElementForCircle(View elem, int distX, int distY) {
          RelativeLayout.LayoutParams lp = createNewRelativeLayoutParams();

          elem.measure(0, 0);
          int deltaX = elem.getMeasuredWidth() / 2;
          int deltaY = elem.getMeasuredHeight() / 2;
          lp.setMargins(distX - deltaX, 0, 0, radius - distY - deltaY);
          elem.setLayoutParams(lp);
          return elem;
}

public CircleView(Context context, int radius, View[] elements) {
          super(context);
          this.radius = radius;

          RelativeLayout.LayoutParams lpView = new RelativeLayout.LayoutParams(
                             RelativeLayout.LayoutParams.FILL_PARENT,
                             RelativeLayout.LayoutParams.FILL_PARENT);
          this.setLayoutParams(lpView);

          View center = new View(context);
          center.setId(centerId);
          RelativeLayout.LayoutParams lpcenter = new RelativeLayout.LayoutParams(
                             0, 0);
          lpcenter.addRule(CENTER_HORIZONTAL);
          lpcenter.addRule(CENTER_VERTICAL);
          center.setLayoutParams(lpcenter);
          this.addView(center);

          this.addView(prepareElementForCircle(elements[0], 0, 0));
          if (elements.length % 2 == 0) {
                   this.addView(prepareElementForCircle(elements[elements.length / 2],
                                      0, 2 * radius));
          }
          if (elements.length > 2) {
                   for (int i = 1; i <= (elements.length - 1) / 2; i++) {
                             int y = i * 4 * radius / elements.length;
                             int x = (int) Math.sqrt(Math.pow(radius, 2)
                                               - Math.pow((radius - y), 2));
                             this.addView(prepareElementForCircle(elements[i], x, y));
                             this.addView(prepareElementForCircle(elements[elements.length
                                               - i], -x, y));
                   }
          }
}

When I pass several views into my CircleView and setContentView of it, everything works fine. But I need also implement ability to rotate this CircleView. So I need to convert my RelativeLayout to the Bitmap. I do it like this:

  public  Bitmap getBitmapFromView() {

    this.measure(MeasureSpec.makeMeasureSpec(createNewRelativeLayoutParams().width, MeasureSpec.UNSPECIFIED),
            MeasureSpec.makeMeasureSpec(createNewRelativeLayoutParams().height, MeasureSpec.UNSPECIFIED));
    this.layout(0, 0, this.getMeasuredWidth(), this.getMeasuredHeight());
    this.setGravity(Gravity.CENTER);
    Bitmap returnedBitmap = Bitmap.createBitmap(this.getMeasuredWidth(), this.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(returnedBitmap);
    this.draw(c);
    return returnedBitmap;
}

as a result I've got my view, but it looks like ugly. So not every view displays and they are not in circle. So my guess is what measuring of the View acts not like it should to be. Maybe, I should to measure all the children? Or maybe call Bitmap convertion method in onPreDraw()? I've tried both of solutions but they didn't work for me.

Callus answered 21/5, 2013 at 10:3 Comment(0)
C
2

I solved this by

 public  Bitmap getBitmapFromView() {
        DisplayMetrics dm = context.getApplicationContext().getResources().getDisplayMetrics(); 
        this.measure(MeasureSpec.makeMeasureSpec(dm.widthPixels, MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(dm.heightPixels, MeasureSpec.EXACTLY));
        this.layout(0, 0, this.getMeasuredWidth(), this.getMeasuredHeight());
        this.setGravity(Gravity.CENTER);
        Bitmap returnedBitmap = Bitmap.createBitmap(this.getMeasuredWidth(),
                this.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(returnedBitmap);
        this.draw(c);
        return returnedBitmap;
    } 

so DisplayMetrics solved my problem.

Callus answered 28/5, 2013 at 15:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.