在自定义视图中的何处设置可绘制对象的边界

发布于 2024-11-25 09:19:46 字数 8947 浏览 7 评论 0原文

概述:我正在尝试创建一些简单的形状(正方形和三角形),然后将它们用作活动的背景图像。形状的大小取决于屏幕的宽度和高度。问题是,即使我设置了这些形状的边界,它们都被绘制得尽可能大,同时仍然适合屏幕。

详细信息:我试图在名为 ControlsOverlayView.java 的重写视图类中创建一个非常简单的背景图像,其上有几个形状。我正在计算画布的大小,然后在 onDraw 方法中调用我的 Paint 方法,因为这是我第一次知道画布有多大的时候。我通过单步执行代码仔细检查了每个形状是否具有正确的边界,但问题是没有一个形状遵守其边界,并且每个形状都在屏幕上绘制尽可能大的尺寸。

public class ControlsOverlayView extends View{

    // graphical constants
    private static int SIDE_ARROW_WIDTH;
    ...
    ...

    public ControlsOverlayView(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

    @Override
    protected void onDraw(Canvas canvas) {

        resize(canvas.getWidth(), canvas.getHeight());
        paintControls();
        super.onDraw(canvas);
    }

    private void resize(int width, int height) {
        // initialize screen size
        SCREEN_WIDTH = width;
        SCREEN_HEIGHT = height;

        HALF_WIDTH = SCREEN_WIDTH / 2;
        HALF_HEIGHT = SCREEN_HEIGHT / 2;

        SIDE_ARROW_HEIGHT = SCREEN_WIDTH/6;
        SIDE_ARROW_WIDTH = SIDE_ARROW_HEIGHT/2;

        // calculate constants
        TEXT_FONT_HEIGHT = Utils.Font_getHeight(TEXT_FONT);

        SCREEN_FRAMED_WIDTH = SCREEN_WIDTH-(2*FRAME_SIZE);
        SCREEN_FRAMED_HEIGHT = SCREEN_HEIGHT-(2*FRAME_SIZE);
    }

    // Creates a background drawable for the control layout including the different coloured panels and the next page arrows
    public void paintControls(){
        // Calculated layout values
        int panelWidth = SIDE_ARROW_WIDTH*3, textViewHeight = (SCREEN_HEIGHT-SIDE_ARROW_HEIGHT)/2;
        int leftArrowX = (SCREEN_WIDTH/8)+(SIDE_ARROW_WIDTH/3), rightArrowX = SCREEN_WIDTH-(SCREEN_WIDTH/4)+(SCREEN_WIDTH/8)-(SIDE_ARROW_WIDTH/3), arrowY = (SCREEN_HEIGHT/2)-(SIDE_ARROW_HEIGHT/2);  

        // Rect array that stores the bounds of each layer of the background
        Rect [] bounds = new Rect[3];
        int i = 0;

        // background
        ShapeDrawable background = new ShapeDrawable(new RectShape());
        bounds[i++] = new Rect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
        background.getPaint().setColor(CONTROLS_BACKGROUND_COLOR);

        // left panel
        ShapeDrawable leftPanel = new ShapeDrawable(new RectShape());
        bounds[i++] = new Rect(0, 0, panelWidth, SCREEN_HEIGHT);
        leftPanel.getPaint().setColor(CONTROLS_PANEL_COLOR);


        // right arrow
        Path rightArrowPath = new Path();
        rightArrowPath.moveTo(SIDE_ARROW_WIDTH, SIDE_ARROW_HEIGHT/2);
        rightArrowPath.lineTo(0, SIDE_ARROW_HEIGHT);
        rightArrowPath.lineTo(0, 0);
        rightArrowPath.lineTo(SIDE_ARROW_WIDTH, SIDE_ARROW_HEIGHT/2);
        rightArrowPath.close();
        ShapeDrawable rightArrow = new ShapeDrawable(new PathShape(rightArrowPath, SIDE_ARROW_WIDTH, SIDE_ARROW_HEIGHT));
        bounds[i++] = new Rect(rightArrowX, arrowY, rightArrowX+SIDE_ARROW_WIDTH, arrowY+SIDE_ARROW_HEIGHT);
        rightArrow.getPaint().setColor(CONTROLS_ARROW_COLOR);

        Drawable [] layers = new Drawable[] { background, leftPanel, rightArrow };
        LayerDrawable controlsBackground = new LayerDrawable(layers);
        controlsBackground.setBounds(0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
        // set the bounds of each layer
        for (i=0;i<controlsBackground.getNumberOfLayers();i++) {
            controlsBackground.getDrawable(i).setBounds(bounds[i]);
        }
        controlsBackground.setAlpha(100);
        controlsLayout.setBackgroundDrawable(controlsBackground);

        controlsLayout.setVisibility(View.VISIBLE);
    }

该活动

名为 ControlsOverlayActivity.java,如下所示:

public class ControlsOverlayActivity extends Activity {

    private ControlsOverlayView overlay;
    private static WattpadApp appState;


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

        setContentView(R.layout.controls_overlay);

        // initialize the controls overlay
        ControlsOverlayView.controlsLayout = (LinearLayout) findViewById(R.id.controls_layout);
        ControlsOverlayView.controlsLayout.setOnClickListener(controlsListener);
        ControlsOverlayView.controlsTextViews = new TextView[] {
                (TextView) findViewById(R.id.controls_text_left_above),
                (TextView) findViewById(R.id.controls_text_right_above),
                (TextView) findViewById(R.id.controls_text_middle),
                (TextView) findViewById(R.id.controls_text_left_below),
                (TextView) findViewById(R.id.controls_text_right_below)
        };
        // initialize the fade in/out animations for the controls overlay
        ControlsOverlayView.controlsFadeIn = new AlphaAnimation(0,1);
        ControlsOverlayView.controlsFadeIn.setDuration(ControlsOverlayView.CONTROLS_FADE_DURATION);
        ControlsOverlayView.controlsFadeOut = new AlphaAnimation(1,0);
        ControlsOverlayView.controlsFadeOut.setDuration(ControlsOverlayView.CONTROLS_FADE_DURATION);
        ControlsOverlayView.controlsFadeOut.setAnimationListener(new AnimationListener(){
            public void onAnimationEnd(Animation animation) {
                //ControlsOverlayView.controlsLayout.setVisibility(View.GONE);
            }
            public void onAnimationRepeat(Animation animation) {}
            public void onAnimationStart(Animation animation) {}
        });
    }

    private OnClickListener controlsListener = new OnClickListener() {

        @Override
        public void onClick(View v) {
            finish();
        }
    };

}

xml 文件名为controls_overlay.xml,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<!--  Controls Overlay -->
<FrameLayout 
 xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/controls_overlay"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
  <wp.wattpad.ui.ControlsOverlayView
                android:layout_width="1dp"
                android:layout_height="1dp"
             />
    <LinearLayout
            android:id="@+id/controls_layout"
            android:orientation="horizontal"
            android:visibility="invisible"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" >

            <!--  Left Panel -->
            <LinearLayout
                android:orientation="vertical"
                android:gravity="left"
                android:layout_width="wrap_content"
                android:layout_height="fill_parent" >
                <TextView android:id="@+id/controls_text_left_above"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center_horizontal|bottom"
                    android:text="@string/controls_prevpage" />
                <TextView android:id="@+id/controls_text_left_below"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center_horizontal|top"
                    android:text="@string/controls_scrollslower" />
            </LinearLayout>
            <!--  Middle Panel -->
            <LinearLayout
                android:orientation="vertical"
                android:layout_width="wrap_content"
                android:layout_height="fill_parent" >
                <TextView android:id="@+id/controls_text_middle"
                    android:layout_width="fill_parent"
                    android:layout_height="fill_parent"
                    android:gravity="center_horizontal|center_vertical"
                    android:text="@string/taptoscroll" />
            </LinearLayout>
            <!--  Right Panel -->
            <LinearLayout
                android:orientation="vertical"
                android:gravity="right"
                android:layout_width="wrap_content"
                android:layout_height="fill_parent" >
                <TextView android:id="@+id/controls_text_right_above"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center_horizontal|bottom"
                    android:text="@string/controls_nextpage" />
                <TextView android:id="@+id/controls_text_right_below"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center_horizontal|top"
                    android:text="@string/controls_scrollfaster" />
            </LinearLayout>
        </LinearLayout>

我真的被困在这里,我想知道从 onDraw() 方法调用调整大小和绘制是否不是最好的地方,但是我不确定还有什么地方可以做到这一点,因为我需要知道高度和宽度屏幕的。我还尝试过调用 super.onDraw() ,这没有改变任何东西。

Overview: I`m trying to create some simple shapes (squares and triangles) and then use them as the background image for an activity. The sizes of the shapes depend on the width and height of the screen. The problem is, even though I am setting the bounds of these shapes, they are all being drawn as big as possible while still fitting inside the screen.

Details: I am trying to create a very simple background image with a couple of shapes on it in an overridden view class called ControlsOverlayView.java. I am figuring out what the size of the canvas and then calling my paint method in the onDraw method, because this is when I first know how big the canvas is. I have double checked by stepping through the code that each shape has the correct bounds, but the problem is that none of the shapes are obeying their bounds, and each shape is drawing as big as it can possibly go on the screen.

public class ControlsOverlayView extends View{

    // graphical constants
    private static int SIDE_ARROW_WIDTH;
    ...
    ...

    public ControlsOverlayView(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

    @Override
    protected void onDraw(Canvas canvas) {

        resize(canvas.getWidth(), canvas.getHeight());
        paintControls();
        super.onDraw(canvas);
    }

    private void resize(int width, int height) {
        // initialize screen size
        SCREEN_WIDTH = width;
        SCREEN_HEIGHT = height;

        HALF_WIDTH = SCREEN_WIDTH / 2;
        HALF_HEIGHT = SCREEN_HEIGHT / 2;

        SIDE_ARROW_HEIGHT = SCREEN_WIDTH/6;
        SIDE_ARROW_WIDTH = SIDE_ARROW_HEIGHT/2;

        // calculate constants
        TEXT_FONT_HEIGHT = Utils.Font_getHeight(TEXT_FONT);

        SCREEN_FRAMED_WIDTH = SCREEN_WIDTH-(2*FRAME_SIZE);
        SCREEN_FRAMED_HEIGHT = SCREEN_HEIGHT-(2*FRAME_SIZE);
    }

    // Creates a background drawable for the control layout including the different coloured panels and the next page arrows
    public void paintControls(){
        // Calculated layout values
        int panelWidth = SIDE_ARROW_WIDTH*3, textViewHeight = (SCREEN_HEIGHT-SIDE_ARROW_HEIGHT)/2;
        int leftArrowX = (SCREEN_WIDTH/8)+(SIDE_ARROW_WIDTH/3), rightArrowX = SCREEN_WIDTH-(SCREEN_WIDTH/4)+(SCREEN_WIDTH/8)-(SIDE_ARROW_WIDTH/3), arrowY = (SCREEN_HEIGHT/2)-(SIDE_ARROW_HEIGHT/2);  

        // Rect array that stores the bounds of each layer of the background
        Rect [] bounds = new Rect[3];
        int i = 0;

        // background
        ShapeDrawable background = new ShapeDrawable(new RectShape());
        bounds[i++] = new Rect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
        background.getPaint().setColor(CONTROLS_BACKGROUND_COLOR);

        // left panel
        ShapeDrawable leftPanel = new ShapeDrawable(new RectShape());
        bounds[i++] = new Rect(0, 0, panelWidth, SCREEN_HEIGHT);
        leftPanel.getPaint().setColor(CONTROLS_PANEL_COLOR);


        // right arrow
        Path rightArrowPath = new Path();
        rightArrowPath.moveTo(SIDE_ARROW_WIDTH, SIDE_ARROW_HEIGHT/2);
        rightArrowPath.lineTo(0, SIDE_ARROW_HEIGHT);
        rightArrowPath.lineTo(0, 0);
        rightArrowPath.lineTo(SIDE_ARROW_WIDTH, SIDE_ARROW_HEIGHT/2);
        rightArrowPath.close();
        ShapeDrawable rightArrow = new ShapeDrawable(new PathShape(rightArrowPath, SIDE_ARROW_WIDTH, SIDE_ARROW_HEIGHT));
        bounds[i++] = new Rect(rightArrowX, arrowY, rightArrowX+SIDE_ARROW_WIDTH, arrowY+SIDE_ARROW_HEIGHT);
        rightArrow.getPaint().setColor(CONTROLS_ARROW_COLOR);

        Drawable [] layers = new Drawable[] { background, leftPanel, rightArrow };
        LayerDrawable controlsBackground = new LayerDrawable(layers);
        controlsBackground.setBounds(0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
        // set the bounds of each layer
        for (i=0;i<controlsBackground.getNumberOfLayers();i++) {
            controlsBackground.getDrawable(i).setBounds(bounds[i]);
        }
        controlsBackground.setAlpha(100);
        controlsLayout.setBackgroundDrawable(controlsBackground);

        controlsLayout.setVisibility(View.VISIBLE);
    }

}

The activity is called ControlsOverlayActivity.java and looks like:

public class ControlsOverlayActivity extends Activity {

    private ControlsOverlayView overlay;
    private static WattpadApp appState;


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

        setContentView(R.layout.controls_overlay);

        // initialize the controls overlay
        ControlsOverlayView.controlsLayout = (LinearLayout) findViewById(R.id.controls_layout);
        ControlsOverlayView.controlsLayout.setOnClickListener(controlsListener);
        ControlsOverlayView.controlsTextViews = new TextView[] {
                (TextView) findViewById(R.id.controls_text_left_above),
                (TextView) findViewById(R.id.controls_text_right_above),
                (TextView) findViewById(R.id.controls_text_middle),
                (TextView) findViewById(R.id.controls_text_left_below),
                (TextView) findViewById(R.id.controls_text_right_below)
        };
        // initialize the fade in/out animations for the controls overlay
        ControlsOverlayView.controlsFadeIn = new AlphaAnimation(0,1);
        ControlsOverlayView.controlsFadeIn.setDuration(ControlsOverlayView.CONTROLS_FADE_DURATION);
        ControlsOverlayView.controlsFadeOut = new AlphaAnimation(1,0);
        ControlsOverlayView.controlsFadeOut.setDuration(ControlsOverlayView.CONTROLS_FADE_DURATION);
        ControlsOverlayView.controlsFadeOut.setAnimationListener(new AnimationListener(){
            public void onAnimationEnd(Animation animation) {
                //ControlsOverlayView.controlsLayout.setVisibility(View.GONE);
            }
            public void onAnimationRepeat(Animation animation) {}
            public void onAnimationStart(Animation animation) {}
        });
    }

    private OnClickListener controlsListener = new OnClickListener() {

        @Override
        public void onClick(View v) {
            finish();
        }
    };

}

And the xml file is called controls_overlay.xml and looks like:

<?xml version="1.0" encoding="utf-8"?>
<!--  Controls Overlay -->
<FrameLayout 
 xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/controls_overlay"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
  <wp.wattpad.ui.ControlsOverlayView
                android:layout_width="1dp"
                android:layout_height="1dp"
             />
    <LinearLayout
            android:id="@+id/controls_layout"
            android:orientation="horizontal"
            android:visibility="invisible"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" >

            <!--  Left Panel -->
            <LinearLayout
                android:orientation="vertical"
                android:gravity="left"
                android:layout_width="wrap_content"
                android:layout_height="fill_parent" >
                <TextView android:id="@+id/controls_text_left_above"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center_horizontal|bottom"
                    android:text="@string/controls_prevpage" />
                <TextView android:id="@+id/controls_text_left_below"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center_horizontal|top"
                    android:text="@string/controls_scrollslower" />
            </LinearLayout>
            <!--  Middle Panel -->
            <LinearLayout
                android:orientation="vertical"
                android:layout_width="wrap_content"
                android:layout_height="fill_parent" >
                <TextView android:id="@+id/controls_text_middle"
                    android:layout_width="fill_parent"
                    android:layout_height="fill_parent"
                    android:gravity="center_horizontal|center_vertical"
                    android:text="@string/taptoscroll" />
            </LinearLayout>
            <!--  Right Panel -->
            <LinearLayout
                android:orientation="vertical"
                android:gravity="right"
                android:layout_width="wrap_content"
                android:layout_height="fill_parent" >
                <TextView android:id="@+id/controls_text_right_above"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center_horizontal|bottom"
                    android:text="@string/controls_nextpage" />
                <TextView android:id="@+id/controls_text_right_below"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center_horizontal|top"
                    android:text="@string/controls_scrollfaster" />
            </LinearLayout>
        </LinearLayout>

I am really stuck here and I am wondering if maybe calling resize and paint from the onDraw() method is not the best place to do it, however I am not sure where else I could do it since I need to know the height and width of the screen. I have also tried moving around the call to super.onDraw() which didn`t change anything.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

不奢求什么 2024-12-02 09:19:46

经过几个令人沮丧的小时后找到了答案。我用 resize(canvas.getWidth(), canvas.getHeight()); 调用 resize() ,它应该是 controlsLayout.getWidth()< /code> 和 controlsLayout.getHeight()。尽管画布高度比视图高度低几个像素,但它完全忽略了边界。不知道为什么会出现这种情况,这非常令人沮丧,但问题已解决。

Found the answer after several frustrating hours. I was calling resize() with resize(canvas.getWidth(), canvas.getHeight()); and it should have been controlsLayout.getWidth() and controlsLayout.getHeight(). Even though the height of the canvas height was a few pixels off of the view's height it was completely ignoring the bounds. No idea why this is the case and it is severely frustrating, but problem solved.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文