11

我有一个 Android 应用程序,它有几个片段。

在这些片段之一中,有

  1. 一个刻字,
  2. 自定义视图,
  3. 两个带按钮的面板。

在自定义视图(第 2 项)中,我需要绘制几个图形,其中一个与视图的大小相关,即应该有一个带圆角的矩形,其大小等于画布的大小减去填充。

为此,我需要获取画布的宽度和高度。

我尝试了以下事情:

  1. 在方法中获取视图的尺寸onSizeChanged(新的宽度/高度)。
  2. 在方法中获取视图的尺寸onLayout
  3. onDraw在方法 ( canvas.getWidth()/getHeight(), View.getMeasuredWidth()/getMeasuredHeight())中获取视图的尺寸。

所有三种方法都返回相同的宽度和高度,但它们都不起作用 - 图形太窄(仅填充大约 60 % 的可用空间而不是 100 %)并且太高(图形的底部不可见)。

RectF确定自定义视图的尺寸(实例)的正确方法是什么?

请注意,我在 Nexus 7 模拟器上以横向模式测试此应用程序。

更新 1 (28.03.2013 21:42 MSK)

对应片段的XML文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/simulation_fragment"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Simulation"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <co.mycompany.ccp.android.impl.simulationcanvas.SimulationCanvasView
        android:id="@+id/simulation_canvas_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="0.8" />

    <LinearLayout
        android:id="@+id/simulationExecutionPanel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="0.1" >

        <Button
            android:id="@+id/restartSimulationButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/restart_simulation" />

        <Button
            android:id="@+id/simulationStepButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/simulation_step" />

        <Button
            android:id="@+id/pauseButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/pause" />

        <Button
            android:id="@+id/continueButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/continue_button" />

        <Button
            android:id="@+id/simulateAdInfinitumButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/simulate_ad_infinitum" />

        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/currentCycleLabel" />

        <TextView
            android:id="@+id/currentCycleIndicator"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Cycle"
            android:textAppearance="?android:attr/textAppearanceMedium" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="0.1" >

        <Button
            android:id="@+id/addCompanyButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/add_company2" />

        <Button
            android:id="@+id/removeCompanyButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/remove_company" />

        <Button
            android:id="@+id/setLabourForceButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/set_labour_force" />
    </LinearLayout>

</LinearLayout>

这是视图(@+id/simulation_canvas_view)的代码:

import co.mycompany.ccp.android.api.economypartsdimensioncalculator.EconomyPartsDimensionCalculator;
import co.mycompany.ccp.android.api.systemboundary.SystemBoundaryGraphicsCalculator;
import co.mycompany.ccp.android.impl.economypartsdimensioncalculator.DefaultEconomyPartsDimensionCalculator;
import co.mycompany.ccp.android.impl.systemboundary.DefaultSystemBoundaryGraphicsCalculator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

/**
 * @author DP118M
 * 
 */
public class SimulationCanvasView extends View {

    private static final int SYSTEM_BOUNDARY_COLOUR = Color.LTGRAY;

    [...]

    private int width = -1;
    private int height= -1;
    private SystemBoundaryGraphicsCalculator systemBoundaryGraphicsCalculator = new DefaultSystemBoundaryGraphicsCalculator();
    [...]
    private Rect systemBoundaryDimensions = new Rect(100, 100, 100 + 100,
            100 + 100);
    private Rect externalEconomyDimensions;

    [...]

    public SimulationCanvasView(final Context aContext) {
        super(aContext);
    }

    public SimulationCanvasView(final Context context, final AttributeSet attrs) {
        super(context, attrs);
    }

    public SimulationCanvasView(final Context context,
            final AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    [...]

    private void updateSystemBoundaryGraphicsCalculatorDimensions() {
        systemBoundaryGraphicsCalculator.setCanvasHeight(height);
        systemBoundaryGraphicsCalculator.setCanvasWidth(width);
        try {
            systemBoundaryGraphicsCalculator.run();
            systemBoundaryDimensions = systemBoundaryGraphicsCalculator
                    .getSystemBoundaryDimensions();
        } catch (final Exception exception) {
            throw new RuntimeException(exception);
        }
    }

    @Override
    protected void onDraw(final Canvas aCanvas) {
        super.onDraw(aCanvas);

        this.width = this.getWidth();
        this.height = this.getHeight();

        updateSystemBoundaryGraphicsCalculatorDimensions();         

        [...]

        drawRectangleWithRoundedEdges(aCanvas, systemBoundaryDimensions,
                SYSTEM_BOUNDARY_COLOUR);

        [...]
    }

    private void drawRectangleWithRoundedEdges(final Canvas aCanvas,
            final Rect aDimensions, int aStrokeColour) {
        final Paint paint = new Paint();

        paint.setColor(aStrokeColour);
        paint.setStrokeWidth(1);
        paint.setStyle(Paint.Style.STROKE);

        aCanvas.drawRoundRect(new RectF(aDimensions), 20, 20, paint);
    }   
}

这是计算圆角矩形尺寸的类:

package co.mycompany.ccp.android.impl.systemboundary;

import android.graphics.Rect;
import co.mycompany.ccp.android.api.systemboundary.SystemBoundaryGraphicsCalculator;

/**
 * @author DP118M
 * 
 */
public class DefaultSystemBoundaryGraphicsCalculator implements
        SystemBoundaryGraphicsCalculator {
    private int canvasWidth;
    private int canvasHeight;
    private int xPadding = SYSTEM_BOUNDARY_X_PADDING;
    private int yPadding = SYSTEM_BOUNDARY_Y_PADDING;
    private Rect systemBoundaryDimensions;

    public void setXPadding(final int xPadding) {
        this.xPadding = xPadding;
    }

    public void setYPadding(final int yPadding) {
        this.yPadding = yPadding;
    }

    @Override
    public Rect getSystemBoundaryDimensions() {
        return systemBoundaryDimensions;
    }

    @Override
    public void setCanvasWidth(final int width) {
        this.canvasWidth = width;
    }

    @Override
    public void setCanvasHeight(final int height) {
        this.canvasHeight = height;
    }

    @Override
    public void run() throws Exception {
        this.systemBoundaryDimensions = new Rect(0 + xPadding, 0 + yPadding,
                Math.max(this.canvasWidth - xPadding, 0), Math.max(
                        this.canvasHeight - yPadding, 0));
    }
}

更新 2

这是屏幕截图:

截屏

更新 3(31.03.2013 19:38 MSK):onLayout如果我从,onSizeChanged或报告的宽度中减去 150 onMeasure,矩形将正确显示。

更新 4 (05.04.2013 21:07 MSK):这是主要活动的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <fragment
        android:id="@+id/menu_pane"
        android:layout_width="0px"
        android:layout_height="match_parent"
        android:layout_weight="1"
        class="co.altruix.ccp.android.impl.fragments.MenuFragment" />

    <FrameLayout
        android:id="@+id/content_fragment2"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" 
        class="co.altruix.ccp.android.impl.fragments.ContentFragment2"/>

</LinearLayout>
4

3 回答 3

2

我看到android:layout_height="wrap_content"自定义视图。

在这种情况下,父/容器ViewGroup希望在测量此视图时知道内容的高度。

但是,要绘制内容,您依赖于布局测量的尺寸,它仍然不知道内容的高度。

设置android:layout_height0dp,这将允许android:layout_weight使用属性,然后视图将根据可用空间具有预先测量的高度。

此外,onSizeChanged()当再次测量布局时,足以通知您尺寸变化。

于 2013-04-05T18:04:54.750 回答
1

试试这个:

view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener(){
        @Override
        public void onGlobalLayout() {

        //capture view width and height here

    }//end onGlobalLayout()

        });

请参阅getViewTreeObserver()。

于 2013-04-06T05:14:06.700 回答
1

根据我对这个问题的评论:

您的顶级布局:您已将 content_fragment2 的宽度设置为 fill_parent,因此它的宽度将与其父线性布局相同。您可能希望 menu_pane 具有固定宽度,没有 layout_weight,并且 content_fragment2 具有 layout_width=0px 和 layout_weight=1。

很高兴这有帮助!

于 2013-04-06T11:09:47.190 回答