我的布局有自定义视图,我将宽度和高度设置为300dp。
经过一番研究(Determining the size of an Android view at runtime)后,我找到了一种以编程方式获取自定义视图宽度和高度的方法。
问题在于我在programmaticaly上获得的尺寸与我在布局上设置的尺寸不同。
显然(在一些测试之后)有一种模式,其中我以编程方式获得的尺寸比布局上设置的尺寸大1.5。
示例:
android:layout_width="270dp" >> myView.getWidth() returns 405
android:layout_width="300dp" >> myView.getWidth() returns 450
这是代码。
有什么想法吗?
布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<com.examples.danilofernandes.housemap.ViewForLayout
android:id="@+id/layout"
android:layout_width="270dp"
android:layout_height="270dp" />
<Button
android:id="@+id/button"
android:text="hello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/layout"/>
</RelativeLayout>
班级:
public class ViewForLayout extends View {
boolean DEBUG_TAG = ActivityForLayout.DEBUG_TAG;
// To use with the Toasts on this Activity.
Context context;
// To use with the Canvas.
Paint paint;
// To advise display orientation.
boolean displayInPortraitMode;
// The plant (bitmap) to be displayed.
int myHousePlant;
// ---
int myDisplayWidth;
int myDisplayHeight;
float myDisplayRatio;
// ---
int myLayoutViewWidth;
int myLayoutViewHeight;
float myLayoutViewRatio;
// ---
float differenceInHeight;
float differenceInWidth;
float scaledPhotoHeight_1;
float scaledPhotoWidth_1;
float scaledPhotoHeight_2;
float scaledPhotoWidth_2;
// ---
Bitmap originalPhoto;
Bitmap scaledPhoto;
float originalPhotoRatio;
float scaledPhotoRatio;
// ---
Rect motionRect;
float motionRectLeft;
float motionRectTop;
float motionRectBottom;
float motionRectRight;
boolean drawMotionRect;
// ---
Rect room1;
Rect room2;
Rect looby;
Rect terrace;
Rect kitchen;
Rect bathroom;
Rect livingRoom;
Rect diningRoom;
Rect accessHall;
Rect serviceArea;
Rect room1Adjunct;
Rect kitchenAdjunct;
Rect serviceAreaAdjunct;
// ---
int drawRoom1;
int drawRoom2;
int drawLooby;
int drawTerrace;
int drawKitchen;
int drawBathroom;
int drawLivingRoom;
int drawDiningRoom;
int drawAccessHall;
int drawServiceArea;
// ---
public ViewForLayout(Context context, AttributeSet attrs) {
super(context, attrs);
// Bind the context to the activity.
this.context = context;
// Makes all connections.
initializeAllVariables();
// The background color of the view
setBackgroundColor(Color.BLACK);
// Resize the picture so that all of it will be visible.
resizePictureToFitIntoScreen();
}
public void initializeAllVariables(){
// Paint setting up
paint = new Paint();
paint.setColor(Color.BLACK);
// Motion rect information
drawMotionRect = false;
// Display data
myDisplayWidth = ActivityForLayout.myDisplayWidth;
myDisplayHeight = ActivityForLayout.myDisplayHeight;
myDisplayRatio = (float) myDisplayHeight / myDisplayWidth;
displayInPortraitMode = ActivityForLayout.displayInPortraitMode;
// Layout date
ViewTreeObserver viewTreeObserver = this.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onGlobalLayout() {
ViewForLayout.this.getViewTreeObserver().removeOnGlobalLayoutListener(this);
myLayoutViewWidth = ViewForLayout.this.getWidth();
myLayoutViewHeight = ViewForLayout.this.getHeight();
}
});
}
myLayoutViewRatio = (float) myLayoutViewHeight / myLayoutViewWidth;
// Photo data
myHousePlant = R.drawable.ilha_de_malaga_transparente;
originalPhoto = BitmapFactory.decodeResource(getResources(), myHousePlant);
originalPhotoRatio = (float) originalPhoto.getHeight() / originalPhoto.getWidth();
// None room will be 'lighted up' at the first place
drawRoom1 = -1;
drawRoom2 = -1;
drawLooby = -1;
drawTerrace = -1;
drawKitchen = -1;
drawBathroom = -1;
drawLivingRoom = -1;
drawDiningRoom = -1;
drawAccessHall = -1;
drawServiceArea = -1;
// The boundaries for all rooms in the house.
room1 = new Rect(64 ,224,265,467);
room2 = new Rect(146, 12,376,211);
looby = new Rect(595, 12,736,94);
terrace = new Rect(389,424,595,468);
kitchen = new Rect(607,104,736,340);
bathroom = new Rect(275,308,376,467);
livingRoom = new Rect(389,215,595,410);
diningRoom = new Rect(389, 12,595,215);
accessHall = new Rect(296,224,389,295);
serviceArea = new Rect(607,362,736,468);
room1Adjunct = new Rect(265,224,283,296);
kitchenAdjunct = new Rect(607,340,670,352);
serviceAreaAdjunct = new Rect(607,352,670,362);
}
@Override
protected void onDraw(Canvas canvas) {
// Whenever onDraw starts, paint color is set to black.
paint.setColor(Color.BLACK);
// Makes the picture to be draw on the center of the view.
float drawInTheMiddleOfTheScreen_Width = (myDisplayWidth - scaledPhotoWidth_2)/2;
float drawInTheMiddleOfTheScreen_Height = (myDisplayHeight - scaledPhotoHeight_2) /2;
// Draw the picture
canvas.drawBitmap(scaledPhoto, drawInTheMiddleOfTheScreen_Width, drawInTheMiddleOfTheScreen_Height, paint);
// To makes the text (for debug info) more visible.
paint.setColor(Color.RED);
paint.setTextSize(25.0f);
// Debug information.
if(DEBUG_TAG) {
canvas.drawText("Device Height: " + myDisplayHeight, 0, 25, paint);
canvas.drawText("Device Width: " + myDisplayWidth, 0, 50, paint);
canvas.drawText("Device Ratio is: " + myDisplayRatio, 0, 75, paint);
canvas.drawText("Original Photo Height: " + originalPhoto.getHeight(), 0, 125, paint);
canvas.drawText("Original Photo Width: " + originalPhoto.getWidth(), 0, 150, paint);
canvas.drawText("Original Photo Ratio is: " + originalPhotoRatio, 0, 175, paint);
canvas.drawText("Scaled Photo Height: " + scaledPhoto.getHeight(), 0, 225, paint);
canvas.drawText("Scaled Photo Width: " + scaledPhoto.getWidth(), 0, 250, paint);
canvas.drawText("Scaled Photo Ratio is: " + scaledPhotoRatio, 0, 275, paint);
canvas.drawText("View Height: " + myLayoutViewHeight, 0, 325, paint);
canvas.drawText("View Width: " + myLayoutViewWidth, 0, 350, paint);
canvas.drawText("View Ratio is: " + myLayoutViewRatio, 0, 375, paint);
}
// Set the color to a transparent yellow
paint.setColor(Color.argb(100,255,255,0));
// Check which room was clicked by the user
// > 1st click - turns the light ON
// > 2nd click - turns the light OFF
if(drawRoom1 > 0) {
canvas.drawRect(room1, paint);
canvas.drawRect(room1Adjunct, paint);
}
if(drawRoom2 > 0) {
canvas.drawRect(room2, paint);
}
if(drawLooby > 0) {
canvas.drawRect(looby, paint);
}
if(drawTerrace > 0) {
canvas.drawRect(terrace, paint);
}
if(drawKitchen > 0) {
canvas.drawRect(kitchen, paint);
canvas.drawRect(kitchenAdjunct, paint);
}
if(drawBathroom > 0){
canvas.drawRect(bathroom,paint);
}
if(drawLivingRoom > 0) {
canvas.drawRect(livingRoom, paint);
}
if(drawDiningRoom > 0) {
canvas.drawRect(diningRoom, paint);
}
if(drawAccessHall > 0) {
canvas.drawRect(accessHall, paint);
}
if(drawServiceArea > 0) {
canvas.drawRect(serviceArea, paint);
canvas.drawRect(serviceAreaAdjunct, paint);
}
// The Rect that is drawn if the user click and drag the finger on the screen.
if(drawMotionRect) {
canvas.drawRect(motionRect, paint);
// Makes the drawn motion rect to be erased from the screen on next onDraw call.
drawMotionRect = false;
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
motionRectLeft = event.getX();
motionRectTop = event.getY();
float xUserTouch = event.getX();
float yUserTouch = event.getY();
if(DEBUG_TAG) {
Toast.makeText(context, "x = " + xUserTouch + ", y = " + yUserTouch, Toast.LENGTH_SHORT).show();
}
if (kitchen.contains((int)event.getX(), (int)event.getY()) || kitchenAdjunct.contains((int)event.getX(), (int)event.getY()) ) {
drawKitchen = drawKitchen * (-1);
// Call onDraw method
invalidate();
}
if (room2.contains((int)event.getX(), (int)event.getY())) {
drawRoom2 = drawRoom2 * (-1);
// Call onDraw method
invalidate();
}
if (room1.contains((int)event.getX(), (int)event.getY()) || room1Adjunct.contains((int)event.getX(), (int)event.getY()) ) {
drawRoom1 = drawRoom1 * (-1);
// Call onDraw method
invalidate();
}
if (livingRoom.contains((int)event.getX(), (int)event.getY())) {
drawLivingRoom = drawLivingRoom * (-1);
// Call onDraw method
invalidate();
}
if (diningRoom.contains((int)event.getX(), (int)event.getY())) {
drawDiningRoom = drawDiningRoom * (-1);
// Call onDraw method
invalidate();
}
if (accessHall.contains((int)event.getX(), (int)event.getY())) {
drawAccessHall = drawAccessHall * (-1);
// Call onDraw method
invalidate();
}
if (serviceArea.contains((int)event.getX(), (int)event.getY()) || serviceAreaAdjunct.contains((int)event.getX(), (int)event.getY()) ) {
drawServiceArea = drawServiceArea * (-1);
// Call onDraw method
invalidate();
}
if (terrace.contains((int)event.getX(), (int)event.getY())) {
drawTerrace = drawTerrace * (-1);
// Call onDraw method
invalidate();
}
if (looby.contains((int)event.getX(), (int)event.getY())) {
drawLooby = drawLooby * (-1);
// Call onDraw method
invalidate();
}
if(bathroom.contains((int)event.getX(), (int)event.getY())){
drawBathroom = drawBathroom * (-1);
// Call onDraw method
invalidate();
}
break;
case MotionEvent.ACTION_MOVE:
// Update the motionRect coordinated at every move.
motionRectRight = event.getX();
motionRectBottom = event.getY();
// Create a new motion Rect to be draw at every move.
motionRect = new Rect((int) motionRectLeft, (int) motionRectTop, (int) motionRectRight, (int) motionRectBottom);
// Permission to draw the motion Rect
drawMotionRect = true;
// Call onDraw method
invalidate();
break;
case MotionEvent.ACTION_UP:
// Do nothing.
}
return true;
}
protected void resizePictureToFitIntoScreen(){
// O redimensionamento da foto é interessante, pois cada tela de celular
// tem uma largura e altura, bem como cada foto. Dependendo das dimensões
// da imagem, resizePictureToFitIntoScreen só um lado (e aplicar a razão largura/altura)
// ao outro já dá certo. As vezes tem que resizePictureToFitIntoScreen duas vezes.
differenceInHeight = originalPhoto.getHeight() - myDisplayHeight;
differenceInWidth = originalPhoto.getWidth() - myDisplayWidth;
// A largura e altura estão fora da tela.
if(differenceInHeight > 0 && differenceInWidth > 0){
// Começamos a resizePictureToFitIntoScreen pelo lado que está mais fora da tela, e depois
// aplicamos ao outro, se necessário.
if(differenceInHeight > differenceInWidth) {
float ratio = (float) myDisplayHeight / originalPhoto.getHeight();
scaledPhotoHeight_1 = ratio * originalPhoto.getHeight();
scaledPhotoWidth_1 = ratio * originalPhoto.getWidth();
// Neste ponto a altura da foto foi redimensionado para ser igual a altura da tela,
// e a largura seguiu a proporção. Mas será que a largura ficou dentro da tela também?
float difLargura_2 = scaledPhotoWidth_1 - myDisplayWidth;
// A altura ficou fora da tela e tem que ser redimensionada
if(difLargura_2 > 0){
float ratio_2 = (float) myDisplayWidth / scaledPhotoWidth_1;
scaledPhotoHeight_2 = ratio_2 * scaledPhotoHeight_1;
scaledPhotoWidth_2 = ratio_2 * scaledPhotoWidth_1;
// Fim, ambas as dimensões foram redimensionadas
}
else{
scaledPhotoHeight_2 = scaledPhotoHeight_1;
scaledPhotoWidth_2 = scaledPhotoWidth_1;
}
} else{
float ratio = (float) myDisplayWidth / originalPhoto.getWidth();
scaledPhotoHeight_1 = ratio * originalPhoto.getHeight();
scaledPhotoWidth_1 = ratio * originalPhoto.getWidth();
// Neste ponto a largura da foto foi redimensionado para ser igual a largura da tela,
// e a altura seguiu a proporção. Mas será que a altura ficou dentro da tela também?
float difAltura_2 = scaledPhotoHeight_1 - myDisplayHeight;
// A altura ficou fora da tela e tem que ser redimensionada
if(difAltura_2 > 0){
float ratio_2 = (float) myDisplayHeight / scaledPhotoHeight_1;
scaledPhotoHeight_2 = ratio_2 * scaledPhotoHeight_1;
scaledPhotoWidth_2 = ratio_2 * scaledPhotoWidth_1;
// Fim, ambas as dimensões foram redimensionadas
}
else{
scaledPhotoHeight_2 = scaledPhotoHeight_1;
scaledPhotoWidth_2 = scaledPhotoWidth_1;
}
}
// Só 01 dimensão precisa ser ajustada
} else if(differenceInHeight > 0 || differenceInWidth > 0){
// Qual que tem que ser ajustada?
if(differenceInHeight > 0) {
float ratio = (float) myDisplayHeight / originalPhoto.getHeight();
scaledPhotoHeight_1 = ratio * originalPhoto.getHeight();
scaledPhotoWidth_1 = ratio * originalPhoto.getWidth();
} else{
float ratio = (float) myDisplayWidth / originalPhoto.getWidth();
scaledPhotoHeight_1 = ratio * originalPhoto.getHeight();
scaledPhotoWidth_1 = ratio * originalPhoto.getWidth();
}
scaledPhotoHeight_2 = scaledPhotoHeight_1;
scaledPhotoWidth_2 = scaledPhotoWidth_1;
// Nenhuma dimensão está fora da tela
} else{
scaledPhotoHeight_2 = originalPhoto.getHeight();
scaledPhotoWidth_2 = originalPhoto.getWidth();
}
scaledPhoto = Bitmap.createScaledBitmap(originalPhoto, (int) scaledPhotoWidth_2, (int) scaledPhotoHeight_2, false);
scaledPhotoRatio = (float) scaledPhoto.getHeight() / scaledPhoto.getWidth();
}
}
答案 0 :(得分:3)
getWidth()和getHeight()以像素为单位返回,但是你输入了dp。取决于设备重新设置,您可能会得到不同的值。
我使用的基本计算
ldpi : 0.75 x
mdpi : 1x
hdpi : 1.5x
xdpi : 2x
xxdpi : 3x