Android: making offscreen bitmap visible when moved - java

I need to start activity with two circular bitmaps in the center, that should instantly animate and move slightly to the side, such that a part of one bitmap is offscreen and not visible. Later on, when the user leaves the activity, it should animate the same way but backwards (move from side to center).
So I've implemented a class that draws these bitmaps in their main location (on the side), and the problem I have right now is that when I am animating those, the offscreen part of the bitmap is never shown, so on my screen I see an ugly moving bitmap that is missing a piece.
This is how the bitmaps are drawn:
public class MyImageView extends ImageView {
private Canvas offscreen;
private static Bitmap pattern;
private static Bitmap logo;
private static int screenWidth, screenHeight; //The real size of the screen
private static int patternDiameter, logoDiameter; //bitmaps' dimensions, both images are circles
private static float topPatternMargin, leftPatternMargin;
private static float topLogoMargin, leftLogoMargin;
public MyImageView (Context context, AttributeSet attrs) {
super(context, attrs);
screenWidth = getSize(context)[0];
screenHeight = getSize(context)[1];
patternDiameter = (int)(screenWidth * (1005.0/1280.0));
logoDiameter = (int)(patternDiameter * (230.0/502.5));
pattern = BitmapFactory.decodeResource(context.getResources(), R.drawable.start_pattern);
pattern = Bitmap.createScaledBitmap(pattern, patternDiameter, patternDiameter, false);
logo = BitmapFactory.decodeResource(context.getResources(), R.drawable.start_logo);
logo = Bitmap.createScaledBitmap(logo, logoDiameter, logoDiameter, false);
leftPatternMargin = (float) ((screenWidth) * (430.0/1280.0) - (patternDiameter/2.0));
topPatternMargin = (float) ((screenHeight - patternDiameter)/2.0);
leftLogoMargin = (float) (leftPatternMargin + patternDiameter/2.0 - logoDiameter/2.0);
topLogoMargin = (float)(topPatternMargin + patternDiameter/2.0 - logoDiameter/2.0);
offscreen = new Canvas(pattern);
}
#Override
protected void onDraw(Canvas canvas) {
if(canvas==offscreen)
super.onDraw(offscreen);
else {
super.draw(offscreen);
canvas.drawBitmap(pattern, leftPatternMargin, topPatternMargin, null);
canvas.drawBitmap(logo, leftLogoMargin, topLogoMargin, null);
}
}
}
So my question is how would I change this code (or maybe some other code) such that, when I make an instance of this class move around, all parts of it are visible to the user?

I found the answer here:
When drawing outside the view clip bounds with Android: how do I prevent underling views from drawing on top of my custom view?
The solution is to add this line to the layout:
android:clipChildren="false"

Related

How to make images on Bitmap smaller?

I am trying to build a simple game on android and while setting the background image and other image assets on my main screen it is appearing too big as shown in the below image.
The actual size of the image is 1920x1080 and I want it to fit my screen like the image shown below:
The code for I have used is:
public class PoliceView extends View {
private Bitmap police;
private Bitmap background;
private Paint scorePaint = new Paint();
private Bitmap life[] = new Bitmap[2];
public PoliceView(Context context) {
super(context);
police = BitmapFactory.decodeResource(getResources(),R.drawable.police);
background = BitmapFactory.decodeResource(getResources(),R.drawable.gamebackground);
scorePaint.setColor(Color.BLACK);
scorePaint.setTextSize(70);
scorePaint.setTypeface(Typeface.DEFAULT_BOLD);
scorePaint.setAntiAlias(true);
life[0] = BitmapFactory.decodeResource(getResources(),R.drawable.heart);
life[1] = BitmapFactory.decodeResource(getResources(),R.drawable.brokenheart);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//The order of draw matters as objects are drawn in this same order
canvas.drawBitmap(background,0,0,null);
canvas.drawBitmap(police, 0, 0, null);
canvas.drawText("Score:",20, 60, scorePaint);
//Three lives for the police
canvas.drawBitmap(life[0],580, 10, null);
canvas.drawBitmap(life[0],680, 10, null);
canvas.drawBitmap(life[0],780, 10, null);
}}
How can I resize the images to fit the screen??
i use this code for resize image
Bitmap tmp = BitmapFactory.decodeFile(mPath);
ResizeWidth = (int) (your size);
ResizeHeight = (int) (your size);
Bitmap bitmap = Bitmap.createBitmap(ResizeWidth, ResizeHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Bitmap scaled = Bitmap.createScaledBitmap(tmp, ResizeWidth, ResizeHeight, true);
int leftOffset = 0;
int topOffset = 0;
canvas.drawBitmap(scaled, leftOffset, topOffset, null);
How to resize bitmap in canvas?
canvas.save(); // Save current canvas params (not only scale)
canvas.scale(scaleX, scaleY);
canvas.restore(); // Restore current canvas params
scale = 1.0f will draw the same visible size bitmap

coverflow images onclick streaming specific sound file (mp3)

i googled coverflow code i found one useful and work great to me (im not professional in android development ), what i need it.
when click on each image it will stream predetermined mp3 song for each image and another click will stop it ,
so each image will have different mp3 song which all mp3 songs stored in app it self .
public class CoverFlowExample extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CoverFlow coverFlow;
coverFlow = new CoverFlow(this);
coverFlow.setAdapter(new ImageAdapter(this));
ImageAdapter coverImageAdapter = new ImageAdapter(this);
//coverImageAdapter.createReflectedImages();
coverFlow.setAdapter(coverImageAdapter);
coverFlow.setSpacing(-25);
coverFlow.setSelection(4, true);
coverFlow.setAnimationDuration(1000);
setContentView(coverFlow);
}
public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
private FileInputStream fis;
private Integer[] mImageIds = {
R.drawable.aa,
R.drawable.aab,
R.drawable.aabb,
R.drawable.aabbb,
R.drawable.aac,
};
private ImageView[] mImages;
public ImageAdapter(Context c) {
mContext = c;
mImages = new ImageView[mImageIds.length];
}
public boolean createReflectedImages() {
//The gap we want between the reflection and the original image
final int reflectionGap = 4;
int index = 0;
for (int imageId : mImageIds) {
Bitmap originalImage = BitmapFactory.decodeResource(getResources(),
imageId);
int width = originalImage.getWidth();
int height = originalImage.getHeight();
//This will not scale but will flip on the Y axis
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
//Create a Bitmap with the flip matrix applied to it.
//We only want the bottom half of the image
Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0, height/2,
width, height/2, matrix, false);
//Create a new bitmap with same width but taller to fit reflection
Bitmap bitmapWithReflection = Bitmap.createBitmap(width
, (height + height/2), Config.ARGB_8888);
//Create a new Canvas with the bitmap that's big enough for
//the image plus gap plus reflection
Canvas canvas = new Canvas(bitmapWithReflection);
//Draw in the original image
canvas.drawBitmap(originalImage, 0, 0, null);
//Draw in the gap
Paint deafaultPaint = new Paint();
canvas.drawRect(0, height, width, height + reflectionGap, deafaultPaint);
//Draw in the reflection
canvas.drawBitmap(reflectionImage,0, height + reflectionGap, null);
//Create a shader that is a linear gradient that covers the reflection
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0, originalImage.getHeight(), 0,
bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff,
TileMode.CLAMP);
//Set the paint to use this shader (linear gradient)
paint.setShader(shader);
//Set the Transfer mode to be porter duff and destination in
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
//Draw a rectangle using the paint with our linear gradient
canvas.drawRect(0, height, width,
bitmapWithReflection.getHeight() + reflectionGap, paint);
ImageView imageView = new ImageView(mContext);
imageView.setImageBitmap(bitmapWithReflection);
imageView.setLayoutParams(new CoverFlow.LayoutParams(120, 180));
imageView.setScaleType(ScaleType.MATRIX);
mImages[index++] = imageView;
}
return true;
}
public int getCount() {
return mImageIds.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
//Use this code if you want to load from resources
ImageView i = new ImageView(mContext);
i.setImageResource(mImageIds[position]);
i.setLayoutParams(new CoverFlow.LayoutParams(430, 430));
i.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
BitmapDrawable drawable = (BitmapDrawable) i.getDrawable();
drawable.setAntiAlias(true);
return i;
//return mImages[position];
}
/** Returns the size (0.0f to 1.0f) of the views
* depending on the 'offset' to the center. */
public float getScale(boolean focused, int offset) {
/* Formula: 1 / (2 ^ offset) */
return Math.max(0, 1.0f / (float)Math.pow(2, Math.abs(offset)));
}
}
}

Cannot use context in class?

I'm currently trying to put in a color from my colors resources xml into my app using ContextCompact.getColor() but for some reason I cannot pass in a single version of context.
I'm using a class as a handler so I am not trying to pass in from an activity. In my activity I can use them, but in my class I cannot pass in getActivityContext() this etc. Nothing works. What do I do?
Also, I'm adding the color to a canvas so I cannot add the color in in an xml.
canvas.drawColor(Color.BLACK);
Is what I'm currently forced to use. I want to replace it with a color from my xml. ( I'm trying to set the background of the canvas essentially )
full code of my class: (I'm making this app as a "note" app so that I can look back on it for future projects, hence all the comments)
public class GameHandling {
private SurfaceHolder holder;
private Resources resources;
private int screenWidth;
private int screenHeight;
private Ball ball;
private Bat player;
private Bat opponent;
public GameHandling(int width, int height, SurfaceHolder holder, Resources resources){
this.holder = holder;
this.resources = resources;
this.screenWidth = width;
this.screenHeight = height;
this.ball = new Ball(screenWidth, screenHeight, 400, 400);
this.player = new Bat(screenWidth, screenHeight, 0, 0, Bat.Position.LEFT);
this.opponent = new Bat(screenWidth, screenHeight, 0, 0, Bat.Position.RIGHT);
}
// setting the ball images to be drawn
public void inIt(){
Bitmap ballShadow = BitmapFactory.decodeResource(resources, R.mipmap.grey_dot);
Bitmap ballImage = BitmapFactory.decodeResource(resources, R.mipmap.red_dot);
Bitmap batPlayer = BitmapFactory.decodeResource(resources, R.mipmap.bat_player);
Bitmap batOpponent = BitmapFactory.decodeResource(resources, R.mipmap.bat_opponent);
ball.inIt(ballImage, ballShadow, 2, 0);
player.inIt(batPlayer, batPlayer, 0, 0);
opponent.inIt(batOpponent, batOpponent, 0, 0);
}
// calling Balls update method to update the ball
public void update(long elapsed){
ball.update(elapsed);
}
public void draw(){
Canvas canvas = holder.lockCanvas(); // Making a canvas object to draw on - .lockcanvas locks canvas
if(canvas != null) {
// draw in area between locking and unlocking
canvas.drawColor(Color.BLACK);
ball.draw(canvas);
player.draw(canvas);
opponent.draw(canvas);
holder.unlockCanvasAndPost(canvas); //-unlockcanvasandposts unlocks the canvas
}
}
}
Change your constructor to this and use ContextCompat.getColor(context,... pattern.
Wherever you are creating this class (activity/fragment), pass the context calling either getActivity() or getApplicationContext()
new GameHandling( getActivity()/getApplicationContext(), ...)
public GameHandling(Context context, int width, int height, SurfaceHolder holder, Resources resources){
this.context = context;
this.holder = holder;
this.resources = resources;
this.screenWidth = width;
this.screenHeight = height;
this.ball = new Ball(screenWidth, screenHeight, 400, 400);
this.player = new Bat(screenWidth, screenHeight, 0, 0, Bat.Position.LEFT);
this.opponent = new Bat(screenWidth, screenHeight, 0, 0, Bat.Position.RIGHT);
}
I kind of came up with a workaround, I created an image with my desirable color and then used that as the background of the app.
However it is still a workaround, so it doesn't solve my issue

libgdx Background TextureRegion repeat

I'm new in libdgx developement and also in game developement. I am reading the book "Learning Libgdx Game Development" from Andreas Oehlke and I am trying to develop my own game in parallel.
I have a problem when I try to add the background. In the book, he uses a color, so it's very simple. But I want to add an image from a texture atlas. The image is to small to recover all the screen, so I want to repeat it. I can't use regBackground.setWrap(TextureWrap.Repeat, TextureWrap.Repeat) because regBackground is not a texture. How i can resolve my problem properly?
public class Background extends AbstractGameObject {
private TextureRegion regBackground;
public Background () {
init();
}
private void init () {
dimension.set(1f, 1f);
regBackground = Assets.instance.levelDecoration.background;
}
public void render (SpriteBatch batch) {
TextureRegion reg = null;
reg = regBackground;
batch.draw(reg.getTexture(),
position.x, position.y,
origin.x, origin.y,
dimension.x, dimension.y,
scale.x, scale.y,
rotation,
reg.getRegionX(), reg.getRegionY(),
reg.getRegionWidth(), reg.getRegionHeight(),
false, false);
}
}
In my Assets class, I have this code to find the region in the texture atlas :
public class AssetLevelDecoration {
public final AtlasRegion background;
public AssetLevelDecoration (TextureAtlas atlas) {
background = atlas.findRegion("background");
}
}
I progressed in solving my problem. I use the setWrap method to repeat my texture :
public class Background extends AbstractGameObject {
private TextureRegion regBackground;
public Background (int width, int heigth) {
init(width, heigth);
}
private void init (int width, int heigth) {
dimension.set(width, heigth);
regBackground = Assets.instance.levelDecoration.background;
origin.x = -dimension.x/2;
origin.y = -dimension.y/2;
}
public void render (SpriteBatch batch) {
TextureRegion reg = null;
reg = regBackground;
Texture test = reg.getTexture();
test.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);
batch.draw(test,
position.x + origin.x, position.y + origin.y,
test.getWidth(), test.getHeight(),
reg.getRegionX(), reg.getRegionY(),
reg.getRegionWidth(), reg.getRegionHeight()
);
}
}
Now, I obtain this, but I just want to repeat my background image (wood square).
http://s24.postimg.org/c1m92ffwx/Capture_du_2013_11_12_15_49_03.jpg
The problem is that the getTexture() recover the all image and not only my background. How can I fix this?
I would just add a comment but I don't have the rep.
To solve the issue of the repeating of the whole texture instead of only the wooden square you have 2 choices. A) separate the textureregion onto a separate texture. B) loop over the to repeat the draw, which should be negligible in terms of performance.
http://badlogicgames.com/forum/viewtopic.php?f=11&t=8883
a simpler approach will be
batch.draw(imageReference,startX,startY,widthOfScreen,heightOfScreen);
batch.draw() is an overloaded method so use only those parameter u need
the syntax is just a pseudo code
MOst importantlu This may give image stretching(depending on image).
I have created an introduction to images including repeating texture here: https://libgdx.info/basic_image/
I hope it helps
This creates an image along this line:

Android zoom canvas in and out on surface view with multiple bit maps drawn with onDraw()

I have a canvas / surfaceview that I am drawing multiple bitmaps so that the user is able to drag around and position anywhere on the canvas. I am looking for a method to create a zoom in and out button that toggles a 50% zoom scale of the canvas when selected.
My app draws multiple bitmaps to the canvas using the onDraw() method.
I have a function now that scales each individual bitmap when the zoom button is toggled but the problem with this is getting the bitmaps to line up relative to each other after the scale. I currently have them scaled off their ending x/y position but by reducing the size 50% the items that were once near each other are no longer that way when zoomed out. I am hoping there is a solution that allows me to accomplish this with the entire canvas at once.
If I need to share some code please let me know.
SurfaceView class where all the drawing happens
public class BuildView extends SurfaceView implements SurfaceHolder.Callback {
then non-scaling drawing happens as canvas.drawBitmap(myBitmap,x,y,null);
Here is my oncreate method, note that BuildView gameView; is initating my surfaceview class;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set full screen view
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
FrameLayout Game = new FrameLayout(this);
LinearLayout GameWidgets = new LinearLayout (this);
gameview = new BuildView(this, null);
//create buttons to lay over the surfaceview
Button AddItemButton = new Button(this);
//Button ZoomInButton = new Button(this);
zoomButton = new Button(this);
TextView MyText = new TextView(this);
AddItemButton.setWidth(250);
AddItemButton.setText("Add Item");
AddItemButton.setId(1);
AddItemButton.setOnClickListener(addItemHandler);
MyText.setText("test");
zoomButton.setWidth(250);
zoomButton.setText("Zoom Out");
zoomButton.setId(2);
zoomButton.setOnClickListener(zoomHandler);
// adding views to the main Game framelayout view * note the view "gameview" is the surface view that everything happens on
GameWidgets.addView(AddItemButton);
GameWidgets.addView(zoomButton);
Game.addView(gameview);
Game.addView(GameWidgets);
int w=getWindowManager().getDefaultDisplay().getWidth()-25;
int h=getWindowManager().getDefaultDisplay().getHeight()-25;
gameview.wid = w; //set width and height in view
gameview.hei = h;
gameview.setWidthHeight(w, h);
setContentView(Game); //trying this out
gameview.updateImage(0, 0); //force bg change
Log.i("views", "Added Game View");
//setContentView(v);
}
since it has been requested here is how I am currently scaling the bitmaps, note that I am looking for another method of scaling the entire canvas. Here is the specifics of my onDraw() method but the full method has more logic in regards to item placement and before scaling I check a boolean flag if the user has selected to scale but i figured you wouldn't want to sift through that much code so I am just putting the pertinent stuff here.
protected void onDraw(Canvas canvas) {
float scaleHeight = getScaled(myBitmap.getHeight());
float scaleWidth = getScaled(myBitmap.getWidth());
scaler.postTranslate(-myBitmap.getWidth() / 4, -itemBit.getHeight() / 4); // Centers image
scaler.postScale(scaleWidth, scaleHeight);
Log.e("onDraw", "item not placed - scaler.postTranslate being called");
scaler.postTranslate(itemX+myBitmap.getWidth()/2, itemY+myBitmap.getHeight()/2);
canvas.drawBitmap(myBitmap, scaler, null);
}
here is my getScaled function;
float getScaled(int orig) {
//return a scaled version
int newScale = orig /2;
float scaled = ((float) newScale) / orig;
return scaled;
}

Categories

Resources