如果父级的初始比例为0,如何使自定义视图的内容与其大小相匹配?

时间:2013-11-21 18:20:51

标签: android view bitmap android-canvas

我正在开发Android游戏,我有一个问题,我一直试图解决一段时间。

我有自定义视图,我已覆盖其onDrawonMeasure。此自定义视图位于LinearLayout或RelativeLayout内,如下所示

<LinearLayout
    android:layout_width="0dip"
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:layout_weight="2">

    <com.leftcorner.craftersofwar.images.BitmapView
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

现在的问题是,在onMeasure函数中,父级的大小为0.我唯一能做的就是根据所需的内容大小扩展我的视图。但是,如果位图大于视图的最终大小,则当我输入onDraw函数时,这将导致布局放错位置。画布的(0,0)坐标位于视图边缘的某处。

我可以在使用((View) this.getParent()).getWidth();进行绘制之前获取父级大小,将位图大小与其进行比较并以正确的比例绘制位图,但是将其绘制到画布会失败,因为位图超出了视图范围在我不知道的地方。

那么,我怎么能把我的这个位图绘制到画布上,以便它实际上可见?如果它也在视图中居中会更好。

以下是我目前的代码:

@Override
protected void onDraw(Canvas canvas) {
    pWidth = ((View) this.getParent()).getWidth();
    pHeight = ((View) this.getParent()).getHeight();

    fWidth = Utility.smaller(pWidth, bWidth);
    fHeight = Utility.smaller(pHeight, bHeight);

    if(bitmap != null){
        // As you can see, I'm not using a custom bitmap class.
        // This function draws the bitmap to the canvas.
        // (x, y, width, height, canvas)
        bitmap.getStorageBitmap().drawScaledBitmap(0, 0, fWidth, fHeight, canvas);
    }
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    bWidth = Math.round(bitmap.getWidth() * scale);
    bHeight = Math.round(bitmap.getHeight() * scale);

    if(bitmap != null) setMeasuredDimension(bWidth, bHeight);
    else setMeasuredDimension(0, 0);
}

2 个答案:

答案 0 :(得分:2)

要获取父级的维度,您可以执行以下操作:

    // set the id of your LinearLayout to parentLayout
    LinearLayout parent = (LinearLayout)findViewById(R.id.parentLayout);
    final ViewTreeObserver observer = parent.getViewTreeObserver();
    observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

        @SuppressLint("NewApi")
        @SuppressWarnings("deprecation")
        @Override
        public void onGlobalLayout() {

            parent.measure(MeasureSpec.UNSPECIFIED,
                    MeasureSpec.UNSPECIFIED);
            int parentHeight = parent.getMeasuredHeight();
            int parentWidth = parent.getMeasuredWidth();

            // set dimensions to bitmap
            bitmap.getLayoutParams().height = parentHeight * scale;
            bitmap.getLayoutParams().width= parentWidth * scale;
            bitmap.requestLayout();

            ViewTreeObserver obs = parent.getViewTreeObserver();

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                obs.removeOnGlobalLayoutListener(this);
            } else {
                obs.removeGlobalOnLayoutListener(this);
            }
        }
    });

您可以将此代码直接放在onCreate

答案 1 :(得分:0)

cYrixmorten给出的答案是正确的,但我以一种不同的方式解决了这个问题。请注意我的LinearLayout的高度设置为wrap_content,但它的宽度来自权重。

这是我的代码:

@Override
protected void onDraw(Canvas canvas) {
    if(getWidth() < 1 || getHeight() < 1){
        requestLayout();
    } else if(bitmap != null){
        bitmap.getStorageBitmap().drawScaledBitmap(0, 0, getWidth(), getHeight(), canvas);
    }
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    if(bitmap != null) {
        bitmapWidth = Math.round(bitmap.getWidth() * scale);
        bitmapHeight = Math.round(bitmap.getHeight() * scale);
    } else {
        setMeasuredDimension(0, 0);
        return;
    }

    parentWidth = MeasureSpec.getSize(widthMeasureSpec);

    if(parentWidth < bitmapWidth){
        bitmapHeight = bitmapHeight * parentWidth / bitmapWidth;
        bitmapWidth = parentWidth;
    }

    setMeasuredDimension(bitmapWidth, bitmapHeight);
}