In my app, I have it so that a button rotates a bitmap 90 degrees each time it is pressed. I have another button that does the same thing but rotates the bitmap -90 degrees.
My issues is that after I press the rotate buttons about 4-6 times, it varies per picture, in any order, I get the error:
`java.lang.NullPointerException`: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference.
Why is this error occurring when the rotation fxn works fine the first few times? I have noticed that the width and height of the bitmap increase each time the rotate button is pushed but that shouldn't crash the app if they are larger than the imageview. I've tried multiple other methods but they seem to crash or just shrink the image.
This is my code:
rotateClockWise.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
Bitmap bitmap = imageViewtoBitmap(imageView);
int width = bitmap.getWidth();
Log.i(TAG, Integer.toString(width));
int height = bitmap.getHeight();
Log.i(TAG, Integer.toString(height));
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
width, height, matrix, true );
imageView.setImageBitmap(rotatedBitmap);
}
});
rotateCCW.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
Bitmap bitmap = imageViewtoBitmap(imageView);
int width = bitmap.getWidth();
Log.i(TAG, Integer.toString(width));
int height = bitmap.getHeight();
Log.i(TAG, Integer.toString(height));
Matrix matrix = new Matrix();
matrix.postRotate(-90);
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
bitmap.getWidth(), bitmap.getHeight(), matrix, true );
imageView.setImageBitmap(rotatedBitmap);
}
});
public static Bitmap imageViewtoBitmap(ImageView imageView){
/**
* Args:
* imageview: an imageview
* Returns:
* the bitmap of the imageview
*/
//convert imageview to bitmap
imageView.setDrawingCacheEnabled(true);
// Without it the view will have a dimension of 0,0 and the bitmap will
be null
imageView.measure(View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED));
// hardcoded so i always know how big image is
imageView.layout(0, 0, imageView.getMeasuredWidth(),
imageView.getMeasuredHeight());
if (imageView == null){
Log.i(TAG, "nothing");
}
imageView.buildDrawingCache(true);
Bitmap bitmapImage = Bitmap.createBitmap(imageView.getDrawingCache());
imageView.setDrawingCacheEnabled(false); // clear drawing cache
return bitmapImage;
}
You should delay click.
Example
in onCreate()
rotateClockWise.setOnClickListener(this);
rotateCCW.setOnClickListener(this);
in method onClick
private long lastClick = 1;
void onClick(View view) {
if(SystemClock.elapsedRealtime() - lastClick < 500) return;
lastClick = SystemClock.elapsedRealtime();
switch (view.getId()) {
case R.id.rotateClockWise: // change id of rotateClockWise
break;
case R.id.rotateCCW: // change id of rotateCCW
break;
}
}
Related
I am using this part of code to create the animation:
private void animate(final ImageView imageView, final Drawable[] images, final int imageIndex,
final boolean forever) {
//imageView <-- The View which displays the images
//images[] <-- Holds R references to the images to display
//imageIndex <-- index of the first image to show in images[]
//forever <-- If equals true then after the last image it starts all over again with the
// first image resulting in an infinite loop. You have been warned.
int fadeInDuration = 1000; // Configure time values here
int timeBetween = 300;
int fadeOutDuration = 1000;
imageView.setVisibility(View.VISIBLE); //Visible or invisible by default -
// this will apply when the animation ends
imageView.setImageDrawable(images[imageIndex]);
Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setInterpolator(new DecelerateInterpolator()); // add this
fadeIn.setDuration(fadeInDuration);
Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new AccelerateInterpolator()); // and this
fadeOut.setStartOffset(fadeInDuration + timeBetween);
fadeOut.setDuration(fadeOutDuration);
AnimationSet animation = new AnimationSet(false); // change to false
animation.addAnimation(fadeIn);
animation.addAnimation(fadeOut);
animation.setRepeatCount(1);
imageView.setAnimation(animation);
animation.setAnimationListener(new Animation.AnimationListener() {
public void onAnimationEnd(Animation animation) {
if (images.length - 1 > imageIndex) {
animate(imageView, images, imageIndex + 1, forever); //Calls itself until it gets to the end of the array
} else {
if (forever) {
animate(imageView, images, 0, forever); //Calls itself to start the animation all
// over again in a loop if forever = true
}
}
}
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
});
}
That piece of code works, the problem is that there's nothing between the fade in and fade out which makes you see whats under those picture (white screen).
I want the fade in to start while the fade out is running so you won't see the white background but always the pictures.
I've tried changing the timeBetween value to be zero (and even negative) which should change the offset of the second animation which will lead to the animations starting at the same time but without success - It only makes the image disappear faster and still doesn't make the requested effect (Fade in and Fade out together)
Could anyone explain how is it possible to make fade in and fade out activate simultaneously
I think the best way to do this is to have two ImageViews, both inside the same FrameLayout so that they overlap (which can also be done with RelativeLayout).
Top ImageView gets image 1.
Bottom ImageView gets image 2.
Animate top ImageView alpha from 1 to 0.
As top ImageView fades out, bottom ImageView becomes visible.
After animation ends, switch bottom image to top and set alpha back to 1.
Load new image in bottom
Repeat animation
Hi I was looking for a solution and found this Question.
I used Bitmaps for my solutions but I'm sure you can change it back.
Same is true for using the 2 imageviews (not passed with function)
This is my solution:
private void animate(final Bitmap[] images, final int imageIndex, final boolean forever) {
final ImageView imageView0 = mImageSlideShow0;
final ImageView imageView1 = mImageSlideShow1;
imageView0.setVisibility(View.VISIBLE);
imageView1.setVisibility(View.VISIBLE);
AnimationSet animationIn = null;
AnimationSet animationOut = null;
//images[] <-- Holds R references to the images to display
//imageIndex <-- index of the first image to show in images[]
//forever <-- If equals true then after the last image it starts all over again with the first image resulting in an infinite loop. You have been warned.
int fadeDuration = 1000; // Configure time values here
Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setInterpolator(new DecelerateInterpolator()); // add this
fadeIn.setDuration(fadeDuration);
Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new AccelerateInterpolator()); // and this
fadeOut.setStartOffset( 2 * fadeDuration); //time that image is visible without any animations
fadeOut.setDuration(fadeDuration);
animationIn = new AnimationSet(false); // change to false
animationIn.addAnimation(fadeIn);
animationIn.setRepeatCount(1);
animationOut = new AnimationSet(false); // change to false
animationOut.addAnimation(fadeOut);
animationOut.setRepeatCount(1);
int animationInIndex = imageIndex;
int animationOutIndex = 0;
//if first image take last one in array
if(imageIndex != 0)
{
animationOutIndex = animationInIndex - 1;
}
else
{
animationOutIndex = images.length - 1;
}
//select the correct fade in / fade out view
if(mCurrentImageViewActive == 0)
{
//set correct image image view
imageView0.setImageBitmap(images[animationInIndex]);
imageView1.setImageBitmap(images[animationOutIndex]);
//set correct animation image view
imageView0.setAnimation(animationIn);
imageView1.setAnimation(animationOut);
//set next fade in view
mCurrentImageViewActive = 1;
}
else
{
imageView1.setImageBitmap(images[animationInIndex]);
imageView0.setImageBitmap(images[animationOutIndex]);
imageView1.setAnimation(animationIn);
imageView0.setAnimation(animationOut);
//set next fade in view
mCurrentImageViewActive = 0;
}
//if fade out is done call next action
animationOut.setAnimationListener(new Animation.AnimationListener()
{
public void onAnimationEnd(Animation animation)
{
if (images.length - 1 > imageIndex)
{
animate(images, imageIndex + 1,forever); //Calls itself until it gets to the end of the array
}
else
{
if (forever)
{
animate( images, 0,forever); //Calls itself to start the animation all over again in a loop if forever = true
}
}
}
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
});
}
I'm trying to do something like this:
Android Map api v2 Custom marker with ImageView
But I'm stuck on using image loader.
Trying:
Bitmap bmImg = imageLoader.loadImageSync(url);
LogCat gives me
04-13 14:11:44.953: E/ImageLoader(18542): android.os.NetworkOnMainThreadException
Here's is my code. I have an ArrayList camera with all information needed (titrle, position, url, etc).
public void drawPicsOnMap()
{
String title = null;
String place = null;
for (int i = 0; i<camera.size(); i++)
{
Bitmap.Config conf = Bitmap.Config.ARGB_8888;
Bitmap bmp = Bitmap.createBitmap(80, 80, conf);
Canvas canvas = new Canvas(bmp);
// paint defines the text color,
// stroke width, size
Paint color = new Paint();
color.setTextSize(35);
color.setColor(Color.BLACK);
Camera cam = camera.get(i);
LatLng coord = new LatLng(cam.lat, cam.lon);
title = Integer.toString(cam.id);
place = cam.place;
String url = cam.img;
Bitmap bmImg = imageLoader.loadImageSync(url);
//modify canvas
canvas.drawBitmap(bmImg, 0,0, color);
canvas.drawText(title, 30, 40, color);
Marker mark = map.addMarker(new MarkerOptions()
.position(coord)
.title(title)
.snippet(place)
.icon(BitmapDescriptorFactory
.fromBitmap(bmp)));
markers.put(mark.getId(), url);
}
}
Try this:
imageLoader.loadImage(url, new SimpleImageLoadingListener(){
#Override
public void onLoadingComplete(String imageUri, View view,
Bitmap loadedImage) {
super.onLoadingComplete(imageUri, view, loadedImage);
//write your code here to use loadedImage
}
});
Here
onLoadingComplete will be called on UI thread which makes it thread safe
You can not do any networking on the main thread. See for description. UIL usually creates the thread and stuff for you when you call displayImage, but loadImageSync does not. Either create a thread and load it or use an AsynTask.
I am trying to make a simple image gallery through which I can set wallpaper; I am using the below code to fetch the files from download folder and display it in scroll view.
I am able to do that, but now I want to fetch the currently displayed image so that I can set that image as wallpaper.
Below is the code I have for my activity class:
public class MainActivity extends Activity {
LinearLayout myGallery;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myGallery = (LinearLayout)findViewById(R.id.mygallery);
String ExternalStorageDirectoryPath = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
.getAbsolutePath();
String targetPath = ExternalStorageDirectoryPath ;
Toast.makeText(getApplicationContext(), targetPath, Toast.LENGTH_LONG).show();
File targetDirector = new File(targetPath);
File[] files = targetDirector.listFiles();
for (File file : files){
myGallery.addView(insertPhoto(file.getAbsolutePath()));
}
}
View insertPhoto(String path){
Bitmap bm = decodeSampledBitmapFromUri(path, 520, 520);
LinearLayout layout = new LinearLayout(getApplicationContext());
layout.setLayoutParams(new LayoutParams(550, 550));//Size of view
layout.setGravity(Gravity.CENTER);
ImageView imageView = new ImageView(getApplicationContext());
imageView.setLayoutParams(new LayoutParams(520, 520));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setImageBitmap(bm);
layout.addView(imageView);
return layout;
}
public Bitmap decodeSampledBitmapFromUri(String path, int reqWidth, int reqHeight) {
Bitmap bm = null;
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
bm = BitmapFactory.decodeFile(path, options);
return bm;
}
public int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
if (width > height) {
inSampleSize = Math.round((float)height / (float)reqHeight);
} else {
inSampleSize = Math.round((float)width / (float)reqWidth);
}
}
return inSampleSize;
}
}
Please tell me how I can fetch the image which is currently displayed in the scroll view.
Thanks
Aman
its been 5 months yet not answered, but i think i will try to answer it.
I think you need a custom view ie. with canvas. create a canvas and then create a bitmap in canvas. After that when you get a bitmap from linear layout in the form of URI, in your code a method decodeSampledBitmapFromUri you are getting a bitmap, simply assign the bitmap to the created bitmap on the canvas.
I'm building an Android app where I have to edit a picture which has been picked from the phone gallery and cropped.
So in my layout, I have an ImageView where I am placing the cropped image
xml file
<ImageView
android:id="#+id/ivEditPhoto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:layout_weight=".90"
android:src="#drawable/app_icon_big" />
Placing the cropped image in ImaveView
bitmapPic = (Bitmap) getIntent().getParcelableExtra(
"CroppedBitmapImage");
picView = (ImageView) findViewById(R.id.ivEditPhoto);
picView.setImageBitmap(bitmapPic);
The image is getting placed correctly. But the problem is when I try to edit it.
I have an edit button and on click of that I do the following which includes registering of On Touch Listener.
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int height = displaymetrics.heightPixels;
int width = displaymetrics.widthPixels;
Bitmap alteredPastedBitmap = Bitmap.createBitmap(bitmapPic.getWidth(),
bitmapPic.getHeight(), bitmapPic.getConfig());
pasteCanvas = new Canvas(alteredPastedBitmap);
paint = new Paint();
paint.setColor(Color.GREEN);
paint.setStrokeWidth(5);
matrix = new Matrix();
pasteCanvas.drawBitmap(bitmapPic, matrix, paint);
picView.setOnTouchListener(this);
Then the following
public boolean onTouch(View v, MotionEvent event) {
Toast.makeText(this, v.getId(), Toast.LENGTH_SHORT).show();
if (v.getId() == R.id.ivEditPhoto) {
Toast.makeText(this, "onTouch", Toast.LENGTH_SHORT).show();
int action = event.getAction();
x = event.getX();
y = event.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
sX = event.getX();
sY = event.getY();
break;
case MotionEvent.ACTION_UP:
if (skewedBitmap == null) {
int resID = 0;
if (imageId == 0)
resID = R.drawable.green_arrow;
else
resID = imageId;
bitmapToPaste = BitmapFactory.decodeResource(
getResources(), resID);
} else {
bitmapToPaste = skewedBitmap;
skewedBitmap = null;
}
pasteCanvas.drawBitmap(bitmapToPaste, sX- (bitmapToPaste.getWidth() / 2),sY- (bitmapToPaste.getHeight() / 2), null);
picView.invalidate();
break;
case MotionEvent.ACTION_CANCEL:
break;
default:
break;
}
}
return true;
}
The issue is:
the bitmapPic.getWidth() and bitmapPic.getHeight() is 160*160 and the onTouch event.getX(); and event.getY(); is beyond the co-ordinates (For example: 150.33 & 500.89) although the image seems to be occupying the whole screen and the touch is on the image. So onTouch doesn't place the bitmap and returns a false.
Could any of you please guide me on this?
I had the same issue in one of my applications. I need to see more of your code but this could be related to the onInterceptTouch() method you need to implement.
If that is not the case, then maybe you can look into this code for help on how to move, modify and rotate bitmaps:
http://adblogcat.com/custom-view-to-draw-rotate-erase-and-convert-images-to-black-and-white/
I wrote this tutorial btw and this is my website and I think is easier for you to follow that tutorial than just paste it here.
I would like to ask on how to implement or add a marker on an imageView.
I rendered an SVG using svglib and used a customImageView so that I can zoom and pan around the image.
here is my code on how i used my customImageView
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
SVG svg;
switch (mNum) {
case 1:
svg = SVGParser.getSVGFromResource(getResources(), R.raw.t1);
break;
case 2:
svg = SVGParser.getSVGFromResource(getResources(), R.raw.t2);
break;
case 3:
svg = SVGParser.getSVGFromResource(getResources(), R.raw.t3);
break;
case 4:
svg = SVGParser.getSVGFromResource(getResources(), R.raw.t4);
break;
default:
svg = SVGParser.getSVGFromResource(getResources(),
R.raw.android);
}
View v = inflater.inflate(R.layout.hello_world, container, false);
View tv = v.findViewById(R.id.text);
imageView = (GestureImageView) v.findViewById(R.id.imageView1);
imageView.setStrict(false);
imageView.setStartingScale(lastScale);
// if(lastXPosition!=0 && lastYPosition!=0)
imageView.setStartingPosition(lastXPosition, lastYPosition);
// Log.i("tag",
// "lastXPosition" + lastXPosition);
// Log.i("tag",
// "lastYPosition" + lastYPosition);
// Log.i("tag",
// "lastScale" + lastScale);
// imageView.setRotation(45);
// imageView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
if (Build.VERSION.SDK_INT > 15)
imageView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
imageView.setImageDrawable(svg.createPictureDrawable());
((TextView) tv).setText("Floor number: " + mNum);
imageView.setBackgroundColor(Color.WHITE);
// tv.setBackgroundDrawable(getResources().getDrawable(
// android.R.drawable.gallery_thumb));
// imageView.setScaleType(ScaleType.CENTER);
// ((GestureImageView)imageView).setScale(x);
return v;
}
Now I would like to add a pin just like the image below...
(source: modality.com)
But my problem is that when I pan around the marker I added is not bonded with the image SVG thus left behind at a certain position when panning...
Here's my code...
NOTE: Not yet final... I'm still looking for a way to get this working and I am using a zoomed in imageview as a map...
#Override
protected void onDraw(Canvas canvas) {
if (layout) {
if (drawable != null && !isRecycled()) {
canvas.save();
float adjustedScale = scale * scaleAdjust;
canvas.translate(x, y);
if (rotation != 0.0f) {
canvas.rotate(rotation);
}
if (adjustedScale != 1.0f) {
canvas.scale(adjustedScale, adjustedScale);
}
drawable.draw(canvas);
canvas.restore();
}
if (drawLock.availablePermits() <= 0) {
drawLock.release();
}
}
// ---add the marker---
Bitmap marker = BitmapFactory.decodeResource(getResources(),
R.drawable.search_marker_icon);
canvas.drawBitmap(marker, 40, 40, null);
Paint mPaint = new Paint();
mPaint.setColor(Color.RED);
canvas.drawCircle(60, 60, 5, mPaint);
super.onDraw(canvas);
}
Thanks.... I'm new to android :) hope you can help me....
This is a nice library for displaying images, which supports zooming/panning and adding pins over the image
https://github.com/davemorrissey/subsampling-scale-image-view
drawable.draw(canvas);
// ---add the marker---
Bitmap marker = BitmapFactory.decodeResource(getResources(),
R.drawable.search_marker_icon);
canvas.drawBitmap(marker, 40, 40, null);
Paint mPaint = new Paint();
mPaint.setColor(Color.RED);
canvas.drawCircle(60, 60, 5, mPaint);
canvas.restore();
}
if (drawLock.availablePermits() <= 0) {
drawLock.release();
}
}
super.onDraw(canvas);
}
You need to do this before canvas.restore..... :D got this solution last year...... thnx for the help guys.... my app is almost done :)
An implementation of an HTML map like element in an Android View:
Supports images as drawable or bitmap in layout
Allows for a list of area tags in xml
Enables use of cut and paste HTML area tags to a resource xml (ie, the ability to take an HTML map - and image and use it with minimal editing)
Supports panning if the image is larger than the device screen
Supports pinch-zoom
Supports callbacks when an area is tapped.
Supports showing annotations as bubble text and provide callback if the bubble is tapped
try this link you will find your solution https://github.com/catchthecows/AndroidImageMap