Before all, I apologies for my English.
I'm a newbie in programming of Android App and I recently discovered the Canvas and Bitmap, so I decided to make a "Game" that can only use landscape. I discovered too the SurfaceView and how implement a background on my SurfaceView, but the first of all is that my background is an image 496x288.
I was searching in internet to learn how I can scaled well to fill all the screen of my phone with the background, and another screens. So I find this code and try to use in my app.
#SuppressLint("WrongCall")
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
Bitmap background = BitmapFactory.decodeResource(getResources(), R.drawable.fondo1escalado);
float scale = (float) background.getHeight() / (float) getHeight();
int newWidth = Math.round((background.getWidth() / scale));
int newHeight = Math.round(background.getHeight() / scale);
scaled = Bitmap.createScaledBitmap(background, newWidth, newHeight, true);
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
#SuppressLint("WrongCall")
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLUE);
canvas.drawBitmap(scaled, 0,0, null);
}
It works, but it doesn't work well. I got this:
(Don't worry about the character)
It scales well but don't fit all the screen (See the blue background).
So, like a good programmer I try to fix this using a GUI that I have designed wich dimensions are 296x912, I used the same code, and it scalates well in the Height but not in the Width for all the screens even a tablet.
This is the code of the GUI
float scalaInterfazAltura = (float) interfaz.getHeight() / (float) getHeight();
int newHeightInterfaz = Math.round(interfaz.getHeight() / scalaInterfazAltura);
int newWidthInterfaz = Math.round(interfaz.getWidth() / scalaInterfazAltura);
scaledinterfaz = Bitmap.createScaledBitmap(interfaz, newWidthInterfaz, newHeightInterfaz, true);
canvas.drawBitmap(scaledinterfaz, getWidth() - interfaz.getWidth()/2, 0, null);
So, my question is: There is a thing to scale well in Surfaceview? I'm doing something wrong?
Thank you.
It happens cause Your display height more than View height.
Try to use surfaceView.getHeight() instead of interfaz.getHeight().
Also You can use
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
in Your Activity before setContentView() to make Your game fullscreen.
Related
For an android 2D-game, I want to create a image scale animation on surfaceview canvas. Following is my working code, I am not sure about the approach is correct or not.
Please suggest me, if I am wrong.
public void drawScaledImage(Canvas canvas, Bitmap bitmap, float scale) {
width = bitmap.getWidth();
height = bitmap.getHeight();
Bitmap tempBitmap = Bitmap.createScaledBitmap(bitmap, (int) (width * scale), (int) (height * scale), false);
canvas.drawBitmap(tempBitmap, getX(), getActualY(), paint);
}
Following code will be executing on every 16ms (FPS 60) with a new scale value.
Please suggest the correct approach to create a image scale animation in android canvas.
I want to create the animation memory and process optimised way.
Thanks.
i am a beginner to android application development.. and with curiosity towards app development i wonder to know the step by step process of creating a reflection to an TEXT or image in android application. please help me with the code
thank you.
You should use a custom view for this and override onDraw(). Something like this should work to reflect:
#Override
protected void onDraw(Canvas canvas) {
int width = getWidth();
int height = getHeight();
canvas.save(Canvas.MATRIX_SAVE_FLAG);
Matrix matrix = new Matrix();
matrix.postTranslate(width, 0);
matrix.postScale(-1, 1);
matrix.postRotate(180, width / 2, height / 2);
canvas.concat(matrix);
super.onDraw(canvas);
canvas.restore();
}
I'm trying to create a ImageView with zoom functions.
I got the zoom function ready, but now I want the image to scale to the ImageView
when starting the Activity. Normally I would use the ScaleType in the xml layout,
but it needs to be Matrix for the zoom function. How can I do this?
I tried the solution from this question: Android image view matrix scale + translate
Matrix m = imageView.getImageMatrix();
RectF drawableRect = new RectF(0, 0, imageWidth, imageHeight);
RectF viewRect = new RectF(0, 0, imageView.getWidth(), imageView.getHeight());
m.setRectToRect(drawableRect, viewRect, Matrix.ScaleToFit.CENTER);
imageView.setImageMatrix(m);
But the problem is I can't use getWidth() and getHeight() because its to early (it only returns 0). Is there a work around? Or how can I fix this?
You need to a add an observer to the ImageView, that will be called when the object is layouted:
imageView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int width = imageView.getWidth();
int height = imageView.getHeight();
// do your stuff
}
});
I had the same problem with matrix, zoom and imageview and the easiest solution I found is to render the image twice, one with scaleType fitcenter and Matrix.
After many (really many..) tempts with setRectToRect and the solution mentioned before (and so on..), I finally find a solution (at least for my case, similar to the post):
In the imageview in your activity xml set fitcenter:
<ImageView
...
android:scaleType="fitCenter"
Then in your java file define a init function on focus changed
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
init();
}
}
private void init() {
maxZoom = 10;
minZoom = 1f;
height = viewHeight;
width = viewWidth;
**Matrix m = imageSWT.getImageMatrix();
imageSWT.setScaleType(ScaleType.MATRIX);
matrix.set(m);**
}
So I'm using the property of fitcenter and then I get his matrix, after that I switch to Matrix mode (for the zoom functionality) and I save the fitcentered-matrix into the matrix-zoom object for keeping the changes when the zoom is used.
I hope this solution could help someone ;)
The only way to be sure of a views width and height is to subclass the view and override onSizeChanged() and use the given width/height or onLayout() and used getMeasuredHeight() and getMeasuredWidth().
This means you're matrix won't be setup until way after onCreate() (until the view is about to be rendered for the first time), but at least the code you've posted could go entirely into the subclassed view.
I'm using a SurfaceView in Android. The application is always in landscape mode.
In my res/drawable folder I have a large background that is also in landscape mode but larger than most display sizes.
Now I would like to set it as the background of the SurfaceView so that it perfectly fits into the display. So the image's height should be equal to the display's height.
How do I do that? Do I have to use alternative resources for ldpi, mdpi, hdpi and xhdpi? But even then I don't know the exact height of the display.
I'm currently using:
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.background), 0, 0, null);
I tried to resize the bitmap using a matrix. But then the quality of the image becomes really poor, doesn't it?
(Of course, the solution should be performant, too.)
protected Bitmap scaled = null;
public void surfaceCreated(SurfaceHolder arg0) {
Bitmap background = BitmapFactory.decodeResource(getResources(), R.drawable.background);
float scale = (float)background.getHeight()/(float)getHeight();
int newWidth = Math.round(background.getWidth()/scale);
int newHeight = Math.round(background.getHeight()/scale);
Bitmap scaled = Bitmap.createScaledBitmap(background, newWidth, newHeight, true);
}
public void onDraw(Canvas canvas) {
canvas.drawBitmap(scaled, 0, 0, null); // draw the background
}
I am trying to create a tab-like interface where I will switch views by sliding left/right. I display to the user what page they are on by adding a blue glow to the back of the tab icon shown here:
I did this by creating a custom view that will draw the background glow (if the tab is selected) and then the icon. My issue is that the glow is too large. All I need to do is to make it smaller so the sides don't get clipped like they are now (the glow overlaps the page on the bottom by design).
The glow was created using a shape drawable in XML (just a simple radial gradient).
I have tried changing the size of the shape in XML but it always comes out the same. I tried adjusting attributes under and tried adjusting the height and width under too.
Constructor:
public TabIconView(Context context, Bitmap tab)
{
super(context);
back = BitmapFactory.decodeResource(getResources(), R.drawable.background_blue_glow);
this.tab = tab;
}
onMeasure and onDraw:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
setMeasuredDimension(tab.getWidth() * 2, tab.getHeight() * 2);
}
#Override
protected void onDraw(Canvas canvas)
{
width = getMeasuredWidth();
height = getMeasuredHeight();
if (selected)
canvas.drawBitmap(back, (width - back.getWidth()) / 2, (height - back.getHeight()) / 2, null);
canvas.drawBitmap(tab, (width - tab.getWidth()) / 2, (height - tab.getHeight()) / 2, null);
super.onDraw(canvas);
}
Any ideas will be greatly appreciated.
One of the versions of Canvas.drawBitmap() lets you specified the width and height that you want the bitmap to have when drawn on screen. You could also simply rescale the bitmap when you load it (the Bitmap class has methods to create scaled versions of bitmaps.)
Figured it out. In case anybody wants to know...
public TabIconView(Context context, Bitmap tab)
{
super(context);
int backSize = (int) (42 * context.getResources().getDisplayMetrics().density + .5f);
b = BitmapFactory.decodeResource(getResources(), R.drawable.background_blue_glow);
back = Bitmap.createScaledBitmap(b, backSize, backSize, false);
this.tab = tab;
}
I had to create a scaled bitmap from the bitmap that was generated from the shapedrawable.