在自定义视图中的何处设置可绘制对象的边界
概述:我正在尝试创建一些简单的形状(正方形和三角形),然后将它们用作活动的背景图像。形状的大小取决于屏幕的宽度和高度。问题是,即使我设置了这些形状的边界,它们都被绘制得尽可能大,同时仍然适合屏幕。
详细信息:我试图在名为 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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
经过几个令人沮丧的小时后找到了答案。我用
resize(canvas.getWidth(), canvas.getHeight());
调用resize()
,它应该是controlsLayout.getWidth()< /code> 和
controlsLayout.getHeight()
。尽管画布高度比视图高度低几个像素,但它完全忽略了边界。不知道为什么会出现这种情况,这非常令人沮丧,但问题已解决。Found the answer after several frustrating hours. I was calling
resize()
withresize(canvas.getWidth(), canvas.getHeight());
and it should have beencontrolsLayout.getWidth()
andcontrolsLayout.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.