My background image is being drawn too big for the canvas - java

The background I'm trying to draw for my app seems to be getting scaled too large for some reason. I made sure the emulator is WVGA800, have it set up in the manifest and layout to be full screen and landscape (just like the image which is 800 x 480). I just don't see where it would scale the image.
Here's a picture of the problem. The image when put in the emulator, and then the actual image.
Here's some relavant code:
/* mBackground instantiated in the class constructor */
mBackground = BitmapFactory.decodeResource( mContext.getResources(), R.drawable.background );
private void doDraw( Canvas canvas )
{
canvas.drawBitmap( mBackground, 0, 0, null );
}
Here's the layout
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<com.project.game.GameView
android:id="#+id/game"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
</RelativeLayout>
</FrameLayout>

one possibility is to create a canvas with a viewport
public void onDraw(Canvas canvas) {
Bitmap myImg = BitmapFactory.decodeResource(getResources(),
R.drawable.cal_blank);
canvas.setViewport(800, 480);
canvas.drawBitmap(iconImg, 0, 0, new Paint(););
}
another way is to scale your image with this method http://www.anddev.org/resize_and_rotate_image_-_example-t621.html

Just a guess - maybe it depends on what folder type is used to put the image in. Could you say where did you put the image? I mean, is it the /res/drawable-hdpi/ or anything else? Have you tried /res/drawable-nodpi/?

Related

ImageView area is smaller than it's actual size

I have assigned a bitmap to a full-screen ImageView with canvas while streaming. Streaming works, the bitmap is shown in ImageView, but the active area of ImageView seems to be smaller than it's actual size. When I set the background color to ImageView, I get this result:
background fills only a small part of marked ImageView...
I assume this is the reason, why all my efforts to scale the bitmap to the size of ImageView do not work.
Here's my layout xml:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingBottom="#dimen/activity_vertical_margin">
<ImageView
android:id="#+id/camera_preview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#DCD5D5"
android:rotation="90"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/button_photo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:onClick="take_photo"
android:text="#string/take_photo"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Assigning bitmap to ImageView:
public void run() {
if (mLastFrame != null) {
mutableBitmap = mLastFrame.copy(Bitmap.Config.RGB_565, true);
if (moffset == OFFSET) {
mBitmap = Bitmap.createBitmap(iv_heigth, iv_width, Bitmap.Config.RGB_565);
mCameraView.setImageBitmap(mBitmap);
mCanvas = new Canvas(mBitmap);
mCanvas.drawBitmap(mutableBitmap, 0, 0, null);
moffset += OFFSET;
}
}
}
ImageView size iv_width, iv_height is checked in onCreate function as follows:
ViewTreeObserver viewTreeObserver = mCameraView.getViewTreeObserver(); //check imageview size
if (viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
mCameraView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
//do some things
iv_width = mCameraView.getWidth();
iv_heigth = mCameraView.getHeight();
}
});
}
I am totally frustrated, hopefully, someone can help a lonely beginner...
This is due to the rotation that was applied to the ImageView. If you remove the rotation, you will be able to see that the ImageView is back to normal. The height of the Imageview is actually matching parent and the same goes for width as well. However, when it is rotated by 90 degrees, you can see the width as the height of the ImageView and vice versa.
In order to tackle this problem, I would recommend removing the rotation from the xml layout that you applied to the ImageView. You can do that for your bitmap drawable instead. Before setting it into the ImageView, rotate the drawable by 90 degrees and then set it to the view.
Here are a few clever ways of rotating a bitmap by 90 degrees. I am just copying one answer from this post for convenience.
public static Bitmap rotateBitmap(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
}
I hope that helps!

Android Design: onDraw() not called after invalidate()

After I call the invalidate() method of my custom view (extends View) the onDraw() method is not called. This is caused by my app design but I not sure how to solve this problem.
I have two Layouts inside a FrameLayout (see below), which should work like layer in photo-editing software. In the code I add a different custom views to layout1 and layout2. After adding the second custom view to the second layout, the onDraw() method of this first custom view is not called after calling invalidate().
<FrameLayout
android:id="#+id/main_frameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/main_layout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />
<LinearLayout
android:id="#+id/main_layout2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />
</FrameLayout>
In both custom views I draw a bitmap over the hole screen size and draw some lines. The drawing is implemented in both custom views like:
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (w > 0 && h > 0) {
this.bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
}
}
#Override
public void onDraw(Canvas canvas) {
canvas.drawBitmap(this.bitmap, 0, 0, new Paint());
drawSomeLines(canvas);
}
It all works fine if I only add one custom view to one layout. Has anybody an idea what is wrong with my structure/code?
I figured it out by myself, maybe the solution will help anybody.
The problem was that I added the custom views to different layouts. I removed the two LinearLayouts and added my custom views directly to the FrameLayout and it works fine.

Java Canvas to XML Layout "Hello World" syntax

I have a simple xml layout that looks like this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".ColorWheel1Activity">
<TextView
android:text="#string/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="Color Wheel 1"
android:id="#+id/Target"
/>
</RelativeLayout>
and a java script in the form of:
public class ColorWheel1Activity extends Activity {
Paint black = new Paint();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bitmap bitmap = Bitmap.createBitmap(400, 400, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
black.setColor(Color.BLACK);
black.setStrokeWidth(5);
canvas.drawOval(100, 200, 1000, 1100, black);
//don'tknow what to put here
}
I want to draw the oval on the canvas to the inside of the ImageView (android:id Target) in the xml layout but don't know how to do this. I have tried setContentView(R.layout.activity_color_wheel1.xml) which sets the xml layout without drawing the picture. I have also tried setContnetView(canvas) and a few of it's variants which set the entire screen as the canvas, displaying the oval but none of the xml Layout. I have made attempts to locate the Target ImageView with findViewById() but these either crashed the app or did nothing.
I do not want to create an entire xml Layout in java.
I have made attempts to locate the Target ImageView with findViewById() but these either crashed the app or did nothing.
Im not sure how locating the Target Imageview would cause a crash; this definitely seems like the way to go. Try getting a reference to Target, like so
ImageView Target = (ImageView) findViewById(R.id.Target);
Then set the bitmap you created to that ImageView:
Target.setImageBitmap(bitmap);

Twitter like Animation for an Android ImageView?

Twitter on iOS has this nice bird animation on start.
(Source)
How can I make such an animation with an Android ImageView?
As simple as:
findViewById(R.id.image_view).animate()
.setStartDelay(500)
.setDuration(1000)
.scaleX(20)
.scaleY(20)
.alpha(0);
Make sure the image view is centered in your layout:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="#mipmap/ic_launcher"/>
</FrameLayout>
To modify the animation further you can:
Delay the animation
Use an decelerating (or other) interpolator
Modify the scale factors
It's called Splash Screen and here is a tutorial how to achieve it - link
The difference is that you need to add after line
setContentView(R.layout.activity_splash);
Following code:
ImageView image = (ImageView) findViewById(R.id.imgLogo);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.my_animation);
image.startAnimation(animation);
And add in your res/anim new file my_animation.xml contains
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/linear_interpolator">
<scale android:fromXScale="1.0" android:fromYScale="1.0"
android:toXScale="5.0" android:toYScale="5.0"
android:duration="3000" android:fillBefore="false"
android:pivotX="50%" android:pivotY="50%" />
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
android:duration="3000"/>
</set>
Agree with above answer but there is another solution: -
THis link may be useful for you just download the code and as per the link suggests
You can create in code:
// create and customize the view
SplashView splashView = new SplashView(context);
// the animation will last 0.5 seconds
splashView.setDuration(500);
// transparent hole will look white before the animation
splashView.setHoleFillColor(Color.WHITE);
// this is the Twitter blue color
splashView.setIconColor(Color.rgb(23, 169, 229));
// a Twitter icon with transparent hole in it
splashView.setIconResource(R.drawable.ic_twitter);
// remove the SplashView from MainView once animation is completed
splashView.setRemoveFromParentOnEnd(true);
or in XML:
<com.yildizkabaran.twittersplash.view.SplashView
xmlns:app="http://schemas.android.com/apk/res/com.yildizkabaran.twittersplash"
android:id="#+id/splash_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:icon="#drawable/ic_twitter"
app:iconColor="#color/twitter_blue"
app:duration="500"
app:holeFillColor="#color/white"
app:removeFromParentOnEnd="true" />
then to run the animation, simply call:
--> run the animation and listen to the animation events (listener can be left as null)
splashView.splashAndDisappear(new ISplashListener(){
#Override
public void onStart(){
}
#Override
public void onUpdate(float completionFraction){
}
#Override
public void onEnd(){
}
});`
Output will be
-Hope you find your answer.

How to set canvas size?

I have a class named SeatsPanel where I draw seats (using drawRect) in the onDraw method. The onDraw method uses Canvas as a parameter, but how do you set size of the Canvas? The reason why I'm asking this question is because this class is being inflated in another class. I know that the canvas has the default height and width of the phone, but I need to make it smaller. How can I do this?
Any help would be appreciated.
I've tried to implement a simple application that draws a black rect within the main activity, that is drawn pushing a button. For example, in the MainActivity:
private Button button1;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button1=(Button)findViewById(R.id.button);
button1.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
switch(v.getId()){
case R.id.button:
LinearLayout ll=(LinearLayout)findViewById(R.id.linearLayout1);
System.out.println(ll.getWidth()+" "+ll.getHeight());
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ll.getWidth(),ll.getHeight());
YourView yourView = new YourView(getBaseContext());
yourView.setBackgroundColor(Color.WHITE);
ll.addView(yourView,params);
break;
}
}
});
}
And in the YourView class:
private Bitmap savedBitmap;
public YourView(Context context) {
super(context);
}
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
System.out.println(canvas.getWidth()+" "+canvas.getHeight());
Paint textPaint = new Paint();
textPaint.setARGB(255, 0, 0, 0);
textPaint.setTextAlign(Paint.Align.RIGHT);
textPaint.setTextSize(11);
textPaint.setTypeface(Typeface.DEFAULT);
canvas.drawColor(Color.WHITE);
System.out.println(canvas.getWidth());
System.out.println(canvas.getHeight());
canvas.drawRect(200, 20, 500, 100, textPaint);
}
The main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Push the button and draw a Rect" />
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button" />
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</LinearLayout>
Might not be applicable in your case, but this works for me
Bitmap animation = BitmapFactory.decodeResource(mContext.getResources(), resourceId, mBitmapOptions); //Get a bitmap from a image file
// Create a bitmap for the part of the screen that needs updating.
Bitmap bitmap = Bitmap.createBitmap(animation.getWidth(), animation.getHeight(), BITMAP_CONFIG);
bitmap.setDensity(DisplayMetrics.DENSITY_DEFAULT);
Canvas canvas = new Canvas(bitmap);
This sets the canvas to the size of the bitmap

Categories