Android scroll through in-app images in a gallery style way - android

I have a GridView of images, which are all in the /res directory (come with the app). When I open one of them, there is no problem. But, I want to be able to scroll between them also in the same way that's done in the gallery, i.e. sliding the finger on the image will cause the next image to appear. Is there any way to do that?
Thanks!

You can use ViewPager
See android viewPager implementation for some good links to learn how to implement it.

I ended up creating a simple implementation of my own:
public class PicView extends View{
private int mBackgroundPicPosition;
private Bitmap mBackgroundPic;
private int m_touchStartPosX;
private EventsActivity m_mainActivity;
private int m_viewWidth;
private int m_viewHeight;
private int m_backgroundX;
private Integer[] m_picIDs;
public PicView(Context context, Integer[] picIDs) {
super(context);
m_mainActivity = (EventsActivity)context;
m_viewWidth = m_mainActivity.mMetrics.widthPixels;
m_viewHeight = m_mainActivity.mMetrics.heightPixels;
m_picIDs = picIDs;
}
public void setBackground(int position) {
Options opts = new Options();
mBackgroundPicPosition = position;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), m_picIDs[position], opts);
mBackgroundPic = BitmapFactory.decodeResource(getResources(), m_picIDs[position], opts);
int picHeight = bitmap.getHeight();
int picWidth = bitmap.getWidth();
mBackgroundPic.recycle();
float xScale, yScale, scale;
if (picWidth > picHeight) {
// rotate the picture
Matrix matrix = new Matrix();
matrix.postRotate(-90);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
picHeight = bitmap.getHeight();
picWidth = bitmap.getWidth();
matrix = null;
}
xScale = ((float)m_viewWidth)/ picWidth;
yScale = ((float)m_viewHeight) / picHeight;
scale = (xScale <= yScale) ? xScale : yScale;
m_backgroundX = (xScale >= yScale) ? (m_viewWidth - (int)(picWidth * scale)) / 2 : 0;
mBackgroundPic = Bitmap.createScaledBitmap(bitmap, (int)(picWidth * scale), (int)(picHeight * scale), true);
bitmap = null;
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
// draw the background
canvas.drawBitmap(mBackgroundPic, m_backgroundX, 0, null);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int eventaction = event.getAction();
int X = (int)event.getX();
switch (eventaction ) {
case MotionEvent.ACTION_DOWN:
m_touchStartPosX = X;
break;
case MotionEvent.ACTION_UP:
//check to see if sliding picture
if (X <= m_touchStartPosX) {
// slide to the left
setBackground(getNextPosition());
} else {
// slide to the right
setBackground(getPrevPosition());
}
m_touchStartPosX = -1;
break;
}
invalidate();
return true;
}
private int getPrevPosition() {
if (mBackgroundPicPosition == 0) {
return m_picIDs.length - 1;
} else {
return mBackgroundPicPosition - 1;
}
}
private int getNextPosition() {
if (mBackgroundPicPosition == m_picIDs.length - 1) {
return 0;
} else {
return mBackgroundPicPosition + 1;
}
}

Related

Is it possible to draw a bitmap multiple times with only 2 instances of the bitmap?

I'm trying to understand game-creation in Android. Therefore I try to program a simple TicTacToe without using buttons or layout files. Instead I want to only use bitmaps.
My Problem is that I can create the board, toggle the "X" and "O" symbol correctly, but my onDraw() only draws 2 symbols simultanously at max and I dont quite understand why or how to solve this.
public class GameScreen extends View {
List<TicTacToeSymbol> symbolList = new ArrayList<>();
float posX;
float posY;
int displayWidth;
int displayHeight;
Bitmap background;
Bitmap bitmapX;
Bitmap bitmapO;
Rect dst = new Rect();
boolean touched = false;
TicTacToeSymbol currentSymbol;
TicTacToeSymbol symbolX;
TicTacToeSymbol symbolO;
Grid grid = new Grid();
// Declaring the coordinates for the colums and rows
int ZERO_COLUMN_X = 0;
int FIRST_COLUMN_X = 480;
int SECOND_COLUMN_X = 910;
int THIRD_COLUMN_X = 1425;
(...)
int centerX = 0;
int centerY = 0;
public GameScreen(Context context) {
super(context);
try {
AssetManager assetManager = context.getAssets();
InputStream inputStream = assetManager.open("tictactoegrid.jpg");
background = BitmapFactory.decodeStream(inputStream);
inputStream = assetManager.open("X.png");
bitmapX = BitmapFactory.decodeStream(inputStream);
inputStream = assetManager.open("O.png");
bitmapO = BitmapFactory.decodeStream(inputStream);
inputStream.close();
// I create only 2 symbols, which might be the problem
symbolX = new TicTacToeSymbol(0, 0, 1);
symbolX.setBitmap(bitmapX);
symbolO = new TicTacToeSymbol(0, 0, 2);
symbolO.setBitmap(bitmapO);
setCurrentSymbol(symbolX, 1);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
Display display = this.getDisplay();
Point size = new Point();
display.getSize(size);
displayWidth = size.x;
displayHeight = size.y;
}
public void toggleCurrentSymbol() {
if (currentSymbol == symbolX) {
currentSymbol = symbolO;
} else {
currentSymbol = symbolX;
}
}
public void setCurrentSymbol(TicTacToeSymbol ticTacToeSymbol, int type) {
this.currentSymbol = ticTacToeSymbol;
if (type == 1) {
currentSymbol.setType(1);
} else
currentSymbol.setType(2);
}
public void setCoordinatesCurrentSymbol(int centerX, int centerY) {
currentSymbol.setPosX(centerX);
currentSymbol.setPosY(centerY);
}
#Override
public void onDraw(Canvas canvas) {
dst.set(0, 0, displayWidth, displayHeight - 200);
canvas.drawBitmap(background, null, dst, null);
if (touched) {
// Checking where the user has clicked
// First row
if (posX >= ZERO_COLUMN_X && posX <= FIRST_COLUMN_X
&& posY > ZERO_ROW_Y && posY < FIRST_ROW_Y) {
centerX = FIRST_CENTER_X;
centerY = FIRST_CENTER_Y;
setCoordinatesCurrentSymbol(centerX, centerY);
grid.placeSignInGrid(0, 0, currentSymbol);
toggleCurrentSymbol();
}
if (posX > FIRST_COLUMN_X && posX <= SECOND_COLUMN_X
&& posY > ZERO_ROW_Y && posY < FIRST_ROW_Y) {
centerX = SECOND_CENTER_X;
centerY = FIRST_CENTER_Y;
setCoordinatesCurrentSymbol(centerX, centerY);
grid.placeSignInGrid(1, 0, currentSymbol);
toggleCurrentSymbol();
}
(...)
}
// Go through the grid, get the symbol at the position and add it to the list of symbols
for (int i = 0; i < Grid.GRID_SIZE; i++) {
for (int j = 0; j < Grid.GRID_SIZE; j++) {
if (grid.getSymbolAtField(i, j) != null) {
if (!symbolList.contains(grid.getSymbolAtField(i, j))) {
symbolList.add(grid.getSymbolAtField(i, j));
}
}
}
}
// Draw every symbol in the list.
for (TicTacToeSymbol ttts : symbolList) {
canvas.drawBitmap(ttts.getBitmap(), ttts.getPosX(), ttts.getPosY(), null);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
touched = true;
posX = event.getX();
posY = event.getY();
invalidate();
return true;
}
return false;
}
}
I create only 2 TicTacToeSymbols, namely symbolXand symbolO. Therefore the symbolList only contains these 2 and draws only those 2.
But how can I draw the same symbol several times? Else I would have to create 9 X-Symbols including the bitmap and 9 O-Symbols to cover all grid-fields with the possible symbols. This would seem wrong / not very elegant?
So how can I draw my 2 symbols several times at the correct positions?
I've looked into several posts like this but could not derive a solution for my problem:
Draw multiple times from a single bitmap on a canvas ... this positions the bitmaps randomly, but I want my symbols on specific positions.

Android - Canvas Black when using Flood-Fill

When I implement my flood-fill class it turns my entire Bitmap black. Obviously this is not the desired effect. I've looked at the following threads:
https://stackoverflow.com/questions/24030858/flood-fill-is-coloring-my-entire-screen
Flood Fill Algorithm Resulting in Black Image
flood fill coloring on android
From what I can see I'm doing everything they've come up with in those solutions, however it hasn't led me to a solution for my problem. So to cut to the chase, here's the code with some brief explanations.
XML
I am using a relative layout and positioning (stacking) two ImageViews directly on top of each other. They both have the same image and this creates the illusion of you being able to draw on the image. However, you are in fact simply drawing on a transparent overlay.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
....
<ImageView
android:id="#+id/drawContainer2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="#id/imageMapperSurfaces"
android:contentDescription="#string/image" />
<ImageView
android:id="#+id/drawContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="#id/imageMapperSurfaces"
android:contentDescription="#string/image" />
...
</RelativeLayout>
Canvas
Then I create my Canvas with this code and I make sure to set my layer types correctly.
public void setCanvas() {
if(mFile != null && mFile.exists()) {
mPictureBitmap = BitmapFactory.decodeFile(mFile.getAbsolutePath());
mBitmap = Bitmap.createScaledBitmap(mPictureBitmap, mImageView.getWidth(), mImageView.getHeight(), false);
mPictureBitmap = mBitmap.copy(Bitmap.Config.ARGB_8888, true);
mBitmap = mPictureBitmap.copy(Bitmap.Config.ARGB_8888, true);
mSceneBitmap = mBitmap.copy(Bitmap.Config.ARGB_8888, true);
mBlurBitmap = blurImage(mPictureBitmap);
mCanvas = new Canvas(mBitmap);
mImageView.setImageBitmap(mBitmap);
mImageView2.setImageBitmap(mPictureBitmap);
mBlur.setImageBitmap(mBlurBitmap);
// failure to set these layer types correctly will result in a black canvas after drawing.
mImageView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
mImageView2.setLayerType(View.LAYER_TYPE_HARDWARE, null);
mImageView.bringToFront();
mAllowedToDraw = true;
setImageViewOnTouch();
}
}
Flood-Fill Implementation
I grab the color, pass my params to the flood-fill object, use the flood-fill method, return the bitmap, and finally draw the new bitmap to my canvas.
int targetColor = mSceneBitmap.getPixel((int) event.getX(), (int) event.getY());
FloodFill fill = new FloodFill(mBitmap, targetColor, Color.argb(100, 255, 0, 0));
fill.floodFill((int) event.getX(), (int) event.getY());
Bitmap bmp = fill.getImage();
mCanvas.drawBitmap(bmp, 0, 0, null);
mImageView.invalidate();
Flood-Fill Class
The boiler-plate Flood-fill algorithm.
public class FloodFill {
protected Bitmap mImage = null;
protected int[] mTolerance = new int[] { 0, 0, 0, 0 };
protected int mWidth = 0;
protected int mHeight = 0;
protected int[] mPixels = null;
protected int mFillColor = 0;
protected int[] mStartColor = new int[] { 0, 0, 0, 0 };
protected boolean[] mPixelsChecked;
protected Queue<FloodFillRange> mRanges;
public FloodFill(Bitmap img) {
copyImage(img);
}
public FloodFill(Bitmap img, int targetColor, int newColor) {
useImage(img);
setFillColor(newColor);
setTargetColor(targetColor);
}
public void setTargetColor(int targetColor) {
mStartColor[0] = Color.red(targetColor);
Log.v("Red", "" + mStartColor[0]);
mStartColor[1] = Color.green(targetColor);
Log.v("Green", "" + mStartColor[1]);
mStartColor[2] = Color.blue(targetColor);
Log.v("Blue", "" + mStartColor[2]);
mStartColor[3] = Color.alpha(targetColor);
Log.v("Alpha", "" + mStartColor[3]);
}
public int getFillColor() {
return mFillColor;
}
public void setFillColor(int value) {
mFillColor = value;
}
public int[] getTolerance() {
return mTolerance;
}
public void setTolerance(int[] value) {
mTolerance = value;
}
public void setTolerance(int value) {
mTolerance = new int[] { value, value, value, value };
}
public Bitmap getImage() {
return mImage;
}
public void copyImage(Bitmap img) {
mWidth = img.getWidth();
mHeight = img.getHeight();
mImage = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(mImage);
canvas.drawBitmap(img, 0, 0, null);
mPixels = new int[mWidth * mHeight];
mImage.getPixels(mPixels, 0, mWidth, 0, 0, mWidth, mHeight);
}
public void useImage(Bitmap img) {
mWidth = img.getWidth();
mHeight = img.getHeight();
mImage = img;
mPixels = new int[mWidth * mHeight];
mImage.getPixels(mPixels, 0, mWidth, 0, 0, mWidth, mHeight);
}
protected void prepare() {
mPixelsChecked = new boolean[mPixels.length];
mRanges = new LinkedList<FloodFillRange>();
}
public void floodFill(int x, int y) {
// Setup
prepare();
if (mStartColor[0] == 0) {
// ***Get starting color.
int startPixel = mPixels[(mWidth * y) + x];
mStartColor[0] = (startPixel >> 16) & 0xff;
mStartColor[1] = (startPixel >> 8) & 0xff;
mStartColor[2] = startPixel & 0xff;
}
LinearFill(x, y);
FloodFillRange range;
while (mRanges.size() > 0) {
range = mRanges.remove();
int downPxIdx = (mWidth * (range.Y + 1)) + range.startX;
int upPxIdx = (mWidth * (range.Y - 1)) + range.startX;
int upY = range.Y - 1;
int downY = range.Y + 1;
for (int i = range.startX; i <= range.endX; i++) {
if (range.Y > 0 && (!mPixelsChecked[upPxIdx]) && CheckPixel(upPxIdx)) LinearFill(i, upY);
if (range.Y < (mHeight - 1) && (!mPixelsChecked[downPxIdx]) && CheckPixel(downPxIdx)) LinearFill(i, downY);
downPxIdx++;
upPxIdx++;
}
}
mImage.setPixels(mPixels, 0, mWidth, 0, 0, mWidth, mHeight);
}
protected void LinearFill(int x, int y) {
int lFillLoc = x;
int pxIdx = (mWidth * y) + x;
while (true) {
mPixels[pxIdx] = mFillColor;
mPixelsChecked[pxIdx] = true;
lFillLoc--;
pxIdx--;
if (lFillLoc < 0 || (mPixelsChecked[pxIdx]) || !CheckPixel(pxIdx)) {
break;
}
}
lFillLoc++;
int rFillLoc = x;
pxIdx = (mWidth * y) + x;
while (true) {
mPixels[pxIdx] = mFillColor;
mPixelsChecked[pxIdx] = true;
rFillLoc++;
pxIdx++;
if (rFillLoc >= mWidth || mPixelsChecked[pxIdx] || !CheckPixel(pxIdx)) {
break;
}
}
rFillLoc--;
FloodFillRange r = new FloodFillRange(lFillLoc, rFillLoc, y);
mRanges.offer(r);
}
protected boolean CheckPixel(int px) {
int red = (mPixels[px] >>> 16) & 0xff;
int green = (mPixels[px] >>> 8) & 0xff;
int blue = mPixels[px] & 0xff;
int alpha = (Color.alpha(mPixels[px]));
return (red >= (mStartColor[0] - mTolerance[0]) && red <= (mStartColor[0] + mTolerance[0])
&& green >= (mStartColor[1] - mTolerance[1]) && green <= (mStartColor[1] + mTolerance[1])
&& blue >= (mStartColor[2] - mTolerance[2]) && blue <= (mStartColor[2] + mTolerance[2])
&& alpha >= (mStartColor[3] - mTolerance[3]) && alpha <= (mStartColor[3] + mTolerance[3]));
}
protected class FloodFillRange {
public int startX;
public int endX;
public int Y;
public FloodFillRange(int startX, int endX, int y) {
this.startX = startX;
this.endX = endX;
this.Y = y;
}
}
}
So that's it, we should have all the pieces to the puzzle but for some reason they aren't working. I'm at a loss and any help is appreciated. Thanks!
I think you're line:
mCanvas.drawBitmap(bmp, 0, 0, null);
might need to be more like
mPaint = new Paint();
mCanvas.drawBitmap(bmp, 0, 0, mPaint);
I am not sure at everything but as far as I can tell you I would try with these solutions:
First:
instead of using decodeFile I rather use decodeInputStream
Second:
As someone has anwsered You better use a Paint() when showing the view
Third:
I am going to ask why do you need that food-fill alghorithm? I think it's too laggy and It looks a little messy to use, why dont you create a new scaled bitmap or something like an opengl effect to do it? because that is the reason why there are graphics cards;

How to set wallpaper to whole screen of device in android

I am using set as wallpaper in my android app. But when I set image as wallpaper its zoom upto some extent on device. I want when I set image as wallpaper. This fit on every screen device. I am using DisplayMetrices but its not working perfect.
Code-
public class FullImageActivity extends Activity {
int position, width, height;
LinearLayout full;
Button btn;
Context context;
DisplayMetrics metrics;
public Integer[] mThumbId = {
R.drawable.kri1, R.drawable.kri2,
R.drawable.kri3, R.drawable.kri4,
R.drawable.kri5, R.drawable.kri6,
R.drawable.kri7, R.drawable.kri8,
R.drawable.kri9
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.full_image);
// get intent data
Intent i = getIntent();
// Selected image id
position = i.getExtras().getInt("id");
full = (LinearLayout) findViewById(R.id.full);
btn = (Button)findViewById(R.id.btn);
changeBackground();
metrics = this.getResources().getDisplayMetrics();
width = metrics.widthPixels;
height = metrics.heightPixels;
btn.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View arg0) {
WallpaperManager myWallpaperManager = WallpaperManager.getInstance(getApplicationContext());
try {
myWallpaperManager.suggestDesiredDimensions(width, height);
myWallpaperManager.setResource(mThumbId[position]);
} catch (IOException e) {
e.printStackTrace();
}
}});
ActivitySwipeDetector activitySwipeDetector = new ActivitySwipeDetector(this);
full.setOnTouchListener(activitySwipeDetector);
}
private void changeBackground(){
full.setBackgroundResource(mThumbId[position]);
}
public class ActivitySwipeDetector implements View.OnTouchListener {
static final String logTag = "ActivitySwipeDetector";
static final int MIN_DISTANCE = 100;
private float downX, upX;
Activity activity;
public ActivitySwipeDetector(Activity activity){
this.activity = activity;
}
public void onRightToLeftSwipe(){
Log.i(logTag, "RightToLeftSwipe!");
if(position < mThumbId.length - 1){
position++;
changeBackground();
}
}
public void onLeftToRightSwipe(){
Log.i(logTag, "LeftToRightSwipe!");
if(position > 0){
position--;
changeBackground();
}
}
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()){
case MotionEvent.ACTION_DOWN: {
downX = event.getX();
return true;
}
case MotionEvent.ACTION_UP: {
upX = event.getX();
float deltaX = downX - upX;
// swipe horizontal?
if(Math.abs(deltaX) > MIN_DISTANCE){
// left or right
if(deltaX < 0) { this.onLeftToRightSwipe(); return true; }
if(deltaX > 0) { this.onRightToLeftSwipe(); return true; }
}
else {
Log.i(logTag, "Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE);
return false; // We don't consume the event
}
return true;
}
}
return false;
}
}
}
Thanks in Advance.
Try this-
Bitmap bmap = BitmapFactory.decodeStream(getResources().openRawResource(mThumb[position]));
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int height = metrics.heightPixels;
int width = metrics.widthPixels;
Bitmap yourbitmap = Bitmap.createScaledBitmap(bmap, width, height, true);
WallpaperManager wallpaperManager = WallpaperManager.getInstance(this);
try {
wallpaperManager.setBitmap(yourbitmap);
} catch (IOException e) {
e.printStackTrace();
}
i'm using this library in my app
it works and it's easy
CropImage
it's open source so you can edit the library as you like
have fun
I guess you need a Image Scaling Algorithm that maintains the image Aspect Ratio,
Store the best image you have in your drawable folder and let this Algorithm scale down the best image to fit the device's Height & Width, maintaining the aspect ratio of the orignal Image.
Bitmap scaleDownLargeImageWithAspectRatio(Bitmap image)
{
int imaheVerticalAspectRatio,imageHorizontalAspectRatio;
float bestFitScalingFactor=0;
float percesionValue=(float) 0.2;
//getAspect Ratio of Image
int imageHeight=(int) (Math.ceil((double) image.getHeight()/100)*100);
int imageWidth=(int) (Math.ceil((double) image.getWidth()/100)*100);
int GCD=BigInteger.valueOf(imageHeight).gcd(BigInteger.valueOf(imageWidth)).intValue();
imaheVerticalAspectRatio=imageHeight/GCD;
imageHorizontalAspectRatio=imageWidth/GCD;
Log.i("scaleDownLargeImageWIthAspectRatio","Image Dimensions(W:H): "+imageWidth+":"+imageHeight);
Log.i("scaleDownLargeImageWIthAspectRatio","Image AspectRatio(W:H): "+imageHorizontalAspectRatio+":"+imaheVerticalAspectRatio);
//getContainer Dimensions
int displayWidth = getWindowManager().getDefaultDisplay().getWidth();
int displayHeight = getWindowManager().getDefaultDisplay().getHeight();
//I wanted to show the image to fit the entire device, as a best case. So my ccontainer dimensions were displayWidth & displayHeight. For your case, you will need to fetch container dimensions at run time or you can pass static values to these two parameters
int leftMargin = 0;
int rightMargin = 0;
int topMargin = 0;
int bottomMargin = 0;
int containerWidth = displayWidth - (leftMargin + rightMargin);
int containerHeight = displayHeight - (topMargin + bottomMargin);
Log.i("scaleDownLargeImageWIthAspectRatio","Container dimensions(W:H): "+containerWidth+":"+containerHeight);
//iterate to get bestFitScaleFactor per constraints
while((imageHorizontalAspectRatio*bestFitScalingFactor <= containerWidth) &&
(imaheVerticalAspectRatio*bestFitScalingFactor<= containerHeight))
{
bestFitScalingFactor+=percesionValue;
}
//return bestFit bitmap
int bestFitHeight=(int) (imaheVerticalAspectRatio*bestFitScalingFactor);
int bestFitWidth=(int) (imageHorizontalAspectRatio*bestFitScalingFactor);
Log.i("scaleDownLargeImageWIthAspectRatio","bestFitScalingFactor: "+bestFitScalingFactor);
Log.i("scaleDownLargeImageWIthAspectRatio","bestFitOutPutDimesions(W:H): "+bestFitWidth+":"+bestFitHeight);
image=Bitmap.createScaledBitmap(image, bestFitWidth,bestFitHeight, true);
//Position the bitmap centre of the container
int leftPadding=(containerWidth-image.getWidth())/2;
int topPadding=(containerHeight-image.getHeight())/2;
Bitmap backDrop=Bitmap.createBitmap(containerWidth, containerHeight, Bitmap.Config.RGB_565);
Canvas can = new Canvas(backDrop);
can.drawBitmap(image, leftPadding, topPadding, null);
return backDrop;
}
private void changeBackground()
{
Drawable inputDrawable = mThumbId[position];
Bitmap bitmap = ((BitmapDrawable)inputDrawable).getBitmap();
bitmap = scaleDownLargeImageWithAspectRatio(bitmap);
#SuppressWarnings("deprecation")
Drawable outDrawable=new BitmapDrawable(bitmap);
full.setBackground(outDrawable);
}
try this code to set image as Wallpaper
public void setWallpaper(final Bitmap bitmp)
{
int screenWidth=getWallpaperDesiredMinimumWidth();
int screenHeight=getWallpaperDesiredMinimumHeight();
try {
WallpaperManager wallpaperManager = WallpaperManager.getInstance(this);
Bitmap btm = getResizedBitmap(bitmp, screenHeight, screenWidth);
wallpaperManager.setBitmap(btm);
Toast toast=Toast.makeText(this, "Done", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.TOP|Gravity.CENTER, 0, 0);
toast.show();
} catch (IOException e) {
e.printStackTrace();
}
}
and
public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
/**
* create a matrix for the manipulation
*/
Matrix matrix = new Matrix();
/**
* resize the bit map
*/
matrix.postScale(scaleWidth, scaleHeight);
/**
* recreate the new Bitmap
*/
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
return resizedBitmap;
}
EDIT :
You are required to just call the that function with desired bitmap
btn.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View arg0) {
setWallpaper(BitmapFactory.decodeResource(FullImageActivity.this.getResources(),
mThumbId[position]));
}});
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);

Scale the Bitmap to screen in Live wallpaper

I'm new in Android Programming I'm Trying to make slideshow animated live wallpaper and all ok but the problem is when I set the wallpaper the scale of image is stretched to screen I want it to scale to all the phone screens and when swipe the wallpaper get the right part of image I Want Advice about this problem.
my code is :
public class CustomWallpaper extends WallpaperService {
#Override
public Engine onCreateEngine() {
return new WallpaperEngine();
}
class WallpaperEngine extends Engine {
//Duration between slides in milliseconds
private final int SLIDE_DURATION = 8;
private int[] mImagesArray;
private int mImagesArrayIndex = 0;
private Thread mDrawWallpaper;
private String mImageScale = "Fit to screen";
private CustomWallpaperHelper customWallpaperHelper;
public WallpaperEngine() {
customWallpaperHelper = new CustomWallpaperHelper(getApplicationContext(), getResources());
mImagesArray = new int[] {R.drawable.image_1,R.drawable.image_2,R.drawable.image_3,R.drawable.image_4,R.drawable.image_5,R.drawable.image_6,R.drawable.image_7,R.drawable.image_8,R.drawable.image_9,R.drawable.image_10,R.drawable.image_11,R.drawable.image_12,R.drawable.image_13,R.drawable.image_14,R.drawable.image_15,R.drawable.image_16,R.drawable.image_17,R.drawable.image_18,R.drawable.image_19,R.drawable.image_20,R.drawable.image_21,R.drawable.image_22,R.drawable.image_23,R.drawable.image_24,R.drawable.image_25,R.drawable.image_26,R.drawable.image_27,R.drawable.image_28,R.drawable.image_29,R.drawable.image_30,R.drawable.image_31,R.drawable.image_32,R.drawable.image_33,R.drawable.image_34,R.drawable.image_35,R.drawable.image_36,R.drawable.image_37,R.drawable.image_38,R.drawable.image_39,R.drawable.image_40,R.drawable.image_41};
mDrawWallpaper = new Thread(new Runnable() {
#Override
public void run() {
try {
while (true) {
drawFrame();
incrementCounter();
Thread.sleep(SLIDE_DURATION);
}
} catch (Exception e) {
//
}
}
});
mDrawWallpaper.start();
}
private void incrementCounter() {
mImagesArrayIndex++;
if (mImagesArrayIndex >= mImagesArray.length) {
mImagesArrayIndex = 0;
}
}
private void drawFrame() {
final SurfaceHolder holder = getSurfaceHolder();
Canvas canvas = null;
try {
canvas = holder.lockCanvas();
if (canvas != null) {
drawImage(canvas);
}
} finally {
if (canvas != null) {
holder.unlockCanvasAndPost(canvas);
}
}
}
private void drawImage(Canvas canvas) {
//Get the image and resize it
Bitmap image = BitmapFactory.decodeResource(getResources(),
mImagesArray[mImagesArrayIndex]);
//Draw background
customWallpaperHelper.setBackground(canvas);
//Scale the canvas
PointF mScale = customWallpaperHelper.getCanvasScale(mImageScale, image.getWidth(), image.getHeight());
canvas.scale(mScale.x, mScale.y);
//Draw the image on screen
Point mPos = customWallpaperHelper.getImagePos(mScale, image.getWidth(), image.getHeight());
canvas.drawBitmap(image, mPos.x, mPos.y, null);
}
}
}
and the other class is:
public class CustomWallpaperHelper {
public final static String IMAGE_SCALE_STRETCH_TO_SCREEN = "Stretch to screen";
public final static String IMAGE_SCALE_FIT_TO_SCREEN = "Fit to screen";
private Context mContext;
private Resources mResources;
private Point screenSize = new Point();
private Bitmap bgImageScaled;
private Point bgImagePos = new Point(0, 0);
public CustomWallpaperHelper(Context mContext, Resources mResources) {
this.mContext = mContext;
this.mResources = mResources;
WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
screenSize.x = display.getWidth();
screenSize.y = display.getHeight();
;
}
private void scaleBackground() {
String imageScale = "Stretch to screen";
Bitmap bgImage = null;
if (imageScale.equals(IMAGE_SCALE_STRETCH_TO_SCREEN)) {
bgImagePos = new Point(0, 0);
bgImageScaled = Bitmap.createScaledBitmap(bgImage, screenSize.x, screenSize.y, true);
}
}
public void setBackground(Canvas canvas) {
if (bgImageScaled != null) {
canvas.drawBitmap(bgImageScaled, bgImagePos.x, bgImagePos.y, null);
} else {
canvas.drawColor(0xff000000);
}
}
public int getScreenWidth() {
return screenSize.x;
}
public int getScreenHeight() {
return screenSize.y;
}
public Point getImagePos(PointF canvasScale, int imageWidth, int imageHeight) {
Point imagePos = new Point();
imagePos.x = (int) (screenSize.x - (imageWidth * canvasScale.x)) / 2;
imagePos.y = (int) (screenSize.y - (imageHeight * canvasScale.y)) / 2;
return imagePos;
}
public PointF getCanvasScale(String imageScale, int imageWidth, int imageHeight) {
PointF canvasScale = new PointF(1f, 1f);
if (imageScale.equals(IMAGE_SCALE_STRETCH_TO_SCREEN)) {
canvasScale.x = getScreenWidth() / (1f * imageWidth);
canvasScale.y = getScreenHeight() / (1f * imageHeight);
} else {
boolean tooWide = false;
boolean tooTall = false;
if (getScreenWidth() < imageWidth) {
tooWide = true;
}
if (getScreenHeight() < imageHeight) {
tooTall = true;
}
if (tooWide && tooTall) {
int x = imageWidth / getScreenWidth();
int y = imageHeight / getScreenHeight();
if (x > y) {
canvasScale.x = getScreenWidth() / (1f * imageWidth);
canvasScale.y = 1;
} else {
canvasScale.x = 1;
canvasScale.y = getScreenHeight() / (1f * imageHeight);
}
} else if (tooWide) {
canvasScale.x = getScreenWidth() / (1f * imageWidth);
canvasScale.y = 1;
} else if (tooTall) {
canvasScale.x = 1;
canvasScale.y = getScreenHeight() / (1f * imageHeight);
}
}
return canvasScale;
}
}
I want Advice for this problem.
Thanks.
no need to do anything just Replace your below method with my code.
private void drawImage(Canvas canvas)
{
Bitmap image = BitmapFactory.decodeResource(getResources(),
mImagesArray[mImagesArrayIndex]);
Bitmap b=Bitmap.createScaledBitmap(image, canvas.getWidth(), canvas.getHeight(), true);
canvas.drawBitmap(b, 0,0, null);
}
I would suggest that you crop the images instead of resizing them. Something like:
Rect r = new Rect(left, top, right, bottom);
Bitmap croppedImage = null;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD_MR1){
InputStream in = mContentResolver.openInputStream(mSaveUri);
BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(in, false);
croppedImage = decoder.decodeRegion(r, null);
} else {
final int width = r.width();
final int height = r.height();
croppedImage = Bitmap.createBitmap(mBitmap, r.left, r.top, width, height);
croppedImage.setDensity(croppedImage.getDensity() * mOutputX / width);
}
return croppedImage;
Hope this helps...

How to set-up automatic collision with just an update() function?

I've just started with Android programming using eclipse and recently came across this problem. I have a bunch of sprites assigned to an arraylist. Now, I want to make it so that collision is detected automatically between sprites but the template I'm currently using can only detect collision between the surface's borders and the moving sprites. Each sprite's position and speed is generated randomly.
How can I change the update() function in my Sprite() class to detect collision between the moving sprites themselves and at the same changing/bouncing to the opposite direction?
Here's my Sprite class template:
package com.gameproject.cai_test;
import java.util.Random;
public Sprite(GameView gameView, Bitmap bmp) {
this.width = bmp.getWidth() / BMP_COLUMNS;
this.height = bmp.getHeight() / BMP_ROWS;
this.gameView = gameView;
this.bmp = bmp;
Random rnd = new Random();
x = rnd.nextInt(gameView.getWidth() - width);
y = rnd.nextInt(gameView.getHeight() - height);
xSpeed = rnd.nextInt(MAX_SPEED * 2) - MAX_SPEED;
ySpeed = rnd.nextInt(MAX_SPEED * 2) - MAX_SPEED;
}
private void update() {
if (x >= gameView.getWidth() - width - xSpeed || x + xSpeed <= 0) {
xSpeed = -xSpeed;
}
x = x + xSpeed;
if (y >= gameView.getHeight() - height - ySpeed || y + ySpeed <= 0) {
ySpeed = -ySpeed;
}
y = y + ySpeed;
currentFrame = ++currentFrame % BMP_COLUMNS;
}
public void onDraw(Canvas canvas) {
update();
int srcX = currentFrame * width;
int srcY = getAnimationRow() * height;
Rect src = new Rect(srcX, srcY, srcX + width, srcY + height);
Rect dst = new Rect(x, y, x + width, y + height);
canvas.drawBitmap(bmp, src, dst, null);
}
private int getAnimationRow() {
double dirDouble = (Math.atan2(xSpeed, ySpeed) / (Math.PI / 2) + 2);
int direction = (int) Math.round(dirDouble) % BMP_ROWS;
return DIRECTION_TO_ANIMATION_MAP[direction];
}
//gameplay operations
//only values from 0 to 9 will be picked; each assigned its own sprite in the list
public int randomValue(){
Random rnd = new Random();
RandomValue = rnd.nextInt(10);
return RandomValue;
}
//sequence operation from addition, subtraction, multiplication, and division
public int produceSum(){
int addOne = 0;
int addTwo = 0;
Sum = addOne + addTwo;
return Sum;
}
public int produceDiff(){
int deductOne = 0;
int deductTwo = 0;
Difference = deductOne - deductTwo;
return Difference;
}
public int produceProduct(){
int multiOne = 0;
int multiTwo = 0;
Product = multiOne * multiTwo;
return Product;
}
public int produceQuotient(){
int divideOne = 0;
int divideTwo = 0;
Quotient = divideOne / divideTwo;
return Quotient;
}
//each time this returns true, the game is reset with new operation
//compares the value of the bubble picked to the random number being compared through operations
public boolean compareBubbleValue(int randomBubble, int bubbleValue){
if (randomBubble == bubbleValue){
return true;
}
return false;
}
}
As you can see, the update() method only checks the collision between the moving sprites and the borders.
Okey, so lets name your array of sprites spriteArray and loop through it twice
public Rect getBounds(){ //put this in your sprite and enemy-class.
return new Rect(x, y, x+width, y+height);
}
Public void checkCollision(){
for (int i = 0; i<spriteArray.size(); i++){
Rect mySprite = spriteArray.get(i).getBounds(); //create rect for every sprite in array
for (int j = 0; j<spriteArray.size(); i++){
Rect myOtherSprite = spriteArray.get(i).getBounds();
if(mySprite.intersect(myOtherSprite)){ //check if they touch
//Todo code here
}
}
}
}
then you just put this method in your update-method.
Here's the coding for the GameView class (pardon the mess, it's a jumble of codes and comments):
package com.gameproject.cai_test;
public class GameView extends SurfaceView {
private Bitmap bmp;
private Bitmap background;
private Bitmap backgroundImage;
private Bitmap pop;
private SurfaceHolder holder;
private GameLoopThread gameLoopThread;
private List<Sprite> sprites = new ArrayList<Sprite>();
private List<TempSprite> temps = new ArrayList<TempSprite>();
private int[] bubbleValue = {0,1,2,3,4,5,6,7,8,9,10};
private long lastClick;
private SpriteObject timer;
private SpriteObject morebanner;
private SpriteObject formulaBox;
private SpriteObject levelbanner1;
private SurfaceHolder surfaceHolder;
public GameView(Context context) {
super(context);
gameLoopThread = new GameLoopThread(this);
timer = new SpriteObject (BitmapFactory.decodeResource(getResources(), R.drawable.hourglass), 1200, 100);
morebanner = new SpriteObject(BitmapFactory.decodeResource(getResources(), R.drawable.morebanner), 650, 300);
formulaBox = new SpriteObject(BitmapFactory.decodeResource(getResources(), R.drawable.formulabox), 650, 600);
background = BitmapFactory.decodeResource(getResources(), R.drawable.background);
backgroundImage = BitmapFactory.decodeResource(getResources(), R.drawable.background);
pop = BitmapFactory.decodeResource(getResources(), R.drawable.pop);
final Toast toast1 = Toast.makeText(context, "LEVEL 1 start", Toast.LENGTH_LONG);
holder = getHolder();
holder.addCallback(new Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
//setSurfaceSize(getWidth(), getHeight());
toast1.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast1.show();
createSprites();
gameLoopThread.setRunning(true);
gameLoopThread.start();
//banner();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
}
private void createSprites() {
sprites.add(createSprite(R.drawable.bubble1));
sprites.add(createSprite(R.drawable.bubble2));
sprites.add(createSprite(R.drawable.bubble3));
sprites.add(createSprite(R.drawable.bubble4));
sprites.add(createSprite(R.drawable.bubble5));
sprites.add(createSprite(R.drawable.bubble6));
sprites.add(createSprite(R.drawable.bubble7));
sprites.add(createSprite(R.drawable.bubble8));
sprites.add(createSprite(R.drawable.bubble9));
sprites.add(createSprite(R.drawable.bubble10));
for (int i = 0; i <= 10; i++){
bubbleValue[i] = sprites.indexOf(i);
}
}
private Sprite createSprite(int resource) {
Bitmap bmp = BitmapFactory.decodeResource(getResources(), resource);
return new Sprite(this, bmp);
}
public void setSurfaceSize(int width, int height)
{
synchronized (surfaceHolder)
{
int canvasWidth = width;
int canvasHeight = height;
backgroundImage = Bitmap.createScaledBitmap(backgroundImage, width, height, true);
}
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
//levelbanner1.draw(canvas);//causes error when applied;for reference only
for (int i = temps.size() - 1; i >= 0; i--) {
temps.get(i).onDraw(canvas);
}
for (Sprite sprite : sprites) {
timer.draw(canvas);
//formulaBox.draw(canvas);
sprite.onDraw(canvas);
}
if (sprites.size() == 0){
morebanner.draw(canvas);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (System.currentTimeMillis() - lastClick > 300) {
lastClick = System.currentTimeMillis();
float x = event.getX();
float y = event.getY();
synchronized (getHolder()) {
for (int i = sprites.size() - 1; i >= 0; i--) {
Sprite sprite = sprites.get(i);
if (sprite.isCollition(x, y)) {
sprites.remove(sprite);
temps.add(new TempSprite(temps, this, x, y, pop));
break;
}
}
}
}
return true;
}
public void update(){
//for possible check of collision bet. sprites
//
}
}
I've tried assigning a Rect for the sprites here and checking collision on the bottom update() function but result gets awry and produces a runtime error. Probably would be better if its automated in the Sprite class update() function, just as it does for border collision.
If you want to have nice and proper collisions between your sprites, maybe looking at a physics engine like http://www.jbox2d.org/ would help.
It will handle a lot of the complex specific cases for you (tunnelling, time of impact, broadphase for early discard...)

Categories

Resources