I have a business need to create the NinePatchDrawable objects at runtime, this is, an exterior .png image is received from a server and it has to be applied in a button's background (for example) as a nine patch.
I have tried to create the NinePatchDrawable object, but the constructor asks me for a "byte[] chunck" that describes the patch. The thing is, I have no idea on how to build this chunk from a bitmap that does not have the 9patch information in it.
Any ideas on this topic? Am I seeing the problem from a wrong perspective?
See my answer for Create a NinePatch/NinePatchDrawable in runtime
I develop a tool to create NinePatchDrawable from (uncompiled) NinePatch bitmap.
See https://gist.github.com/knight9999/86bec38071a9e0a781ee .
The method
NinePatchDrawable createNinePatchDrawable(Resources res, Bitmap bitmap)
helps you.
For example,
ImageView imageView = (ImageView) findViewById(R.id.imageview);
Bitmap bitmap = loadBitmapAsset("my_nine_patch_image.9.png", this);
NinePatchDrawable drawable = NinePatchBitmapFactory.createNinePatchDrawable(getResources(), bitmap);
imageView.setBackground( drawable );
where
public static final Bitmap loadBitmapAsset(String fileName,Context context) {
final AssetManager assetManager = context.getAssets();
BufferedInputStream bis = null;
try {
bis = new BufferedInputStream(assetManager.open(fileName));
return BitmapFactory.decodeStream(bis);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bis.close();
} catch (Exception e) {
}
}
return null;
}
In this case, the my_nine_patch_image.9.png is under the assets directory.
I've answered this over at question 5519768. Keep in mind the differences between "source" and "compiled" ninepatch images.
Related
I generate Picture in my code like this:
try {
SVG svg = SVG.getFromResource(this, R.raw.splatter);
SVGImageView svgImageView = new SVGImageView(this);
svgImageView.setSVG(svg);
svgImageView.setLayoutParams(
new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
RelativeLayout layout =
(RelativeLayout) findViewById(R.id.main_layout);
layout.addView(svgImageView);
//svg.renderViewToPicture(Integer.toString(R.id.map), layout.getWidth(), layout.getHeight());
svg.renderToPicture();
} catch (SVGParseException e) {
e.printStackTrace();
}
Now I need set this Picture to my ImageView. How can I do this?
Do you really need to put the svg in res/raw? You can just reference it directly from res/drawable as you would a normal image (ie. imageView.setImageResource(R.drawable.splatter)). This site has a pretty good SVG to Android readable SVG tool.
Bitmap PicturetoDrawable(Picture picture) {
return Bitmap.createBitmap(picture.getWidth(), picture.getHeight(), Bitmap.Config.ARGB_8888);
}
I would like to use Glide to load bitmap to ImageView after cropping and re-sizing a bitmap.
I don't want to use ImageView.setImageBitmap(bitmap); because I am loading lots of images and it might be taking up some memory, although the images are small in size, I just need to use Glide because I know it optimises image caching.
I read this post, but I didn't quite understand his solution when I tried implementing it. So maybe someone has a cleaner and more easily understandable solution.
This is my code which picks up an image and creates a bitmap out of it.
I need to use glide instead of ImageView.setImageBitmap(bitmap);.
new AsyncTask<String, Void, Void>() {
Bitmap theBitmap = null;
Bitmap bm = null;
#Override
protected Void doInBackground(String... params) {
String TAG = "Error Message: ";
try {
//Load the image into bitmap
theBitmap = Glide.
with(mContext).
load("http://example.com/imageurl").
asBitmap().
into(-1, -1).
get();
//resizes the image to a smaller dimension out of the main image.
bm = Bitmap.createBitmap(theBitmap, 0, 0, 210, 80);
} catch (final ExecutionException e) {
Log.e(TAG, e.getMessage());
} catch (final InterruptedException e) {
Log.e(TAG, e.getMessage());
} catch (final NullPointerException e) {
//
}
return null;
}
#Override
protected void onPostExecute(Void dummy) {
if (null != theBitmap) {
//Set image to imageview.
**// I would like to Use Glide to set the image view here Instead of .setImageBitmap function**
holder.mImageView.setImageBitmap(bm);
holder.mImageView.setAdjustViewBounds(true);
holder.mImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
}
}
}.execute();
You don't need AsyncTask to load image with Glide. Glide load image asynchronys.
Try to use this code:
Glide.with(mContext)
.load("http://example.com/imageurl")
.asBitmap()
.into(new SimpleTarget<Bitmap>() {
#Override
public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
// you can do something with loaded bitmap here
// .....
holder.mImageView.setImageBitmap(resource);
}
});
So the problem is
1. We are using listView for chat application
2 . each time a chat is sent or rec we update the arrayList and update the adapter and do notifydatasetAdaper() for refreshing the list view.
3. So if we send 10 images in chat and then send 11th chat msg(let say text chtat) and then call notifydatasetadapter() in this case all the 10 images are refreshing.
4. So i need to stop this refreshing of images.
5. ListView must be refreshed without refreshing the images
So any idea how can i achieve this.. or may be m on the wrong path please show me the correct way of doing it.....!!!
I also tried using picaso but the library is conflicting with okhttp library ....!!!
Also this is the way i am showing the images
public class ImageFromSd extends AsyncTask<Object, Bitmap, Bitmap> {
ImageView im;
// int targetWidth = 200;
// int targetHeight = 200;
#Override
protected Bitmap doInBackground(Object... params) {
// TODO Auto-generated method stub
Bitmap bitmap = null;
try {
im = (ImageView) params[0];
String path = (String) im.getTag();
Log.d("ankit", "image path :::::" + path);
bitmap = BitmapFactory.decodeFile(path);
// bitmap.compress(CompressFormat.JPEG, 100, new
// FileOutputStream(
// path));
//
// bitmap = Bitmap.createScaledBitmap(bitmap, targetWidth,
// targetHeight, false);
}
// catch (FileNotFoundException e) {
// e.printStackTrace();
// bitmap = null;
// }
catch (OutOfMemoryError e) {
e.printStackTrace();
bitmap = null;
} catch (NullPointerException e) {
e.printStackTrace();
bitmap = null;
} catch (Exception e) {
e.printStackTrace();
bitmap = null;
}
return bitmap;
}
#Override
protected void onPostExecute(Bitmap result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
if (result != null) {
im.setScaleType(ScaleType.FIT_CENTER);
im.setImageBitmap(result);
}
}
}
and then calling it like this
im.setTag(items.get(i).getTextChat());
new ImageFromSd().execute(im);
Firstly, You have to refresh listview as any data updates within listview.
Secondly, the method you using for loading image is not good.
try this library to load remote or local image. it maintains cache automatically and very efficient for image loading.
Universal Image Loader
https://github.com/nostra13/Android-Universal-Image-Loader
I am not checking for the bitmap is already cached or not.
Everytime when a imageView is passed to AsynTask, i am decoding from the path. Which is wrong.
I shouuld LRUCache or DiskCache and store the bitmap in cache with the path as key.
http://developer.android.com/reference/android/util/LruCache.html
http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
I have a Adobe Air application that intend to take a screenshot with Native Extension on Android device, but the java code returns a black image.
public FREObject call(FREContext context, FREObject[] params) {
View view = context.getActivity().getWindow().getDecorView();
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap image = view.getDrawingCache();
}
I don't know much about Adobe Air. My java code runs exactly on Android Java Application, but returns black image on Adobe Air Android Application with Native Extension.
Is there any solution or any way to take a screenshot using Java in NativeExtension?
Thanks much!
Could be that you are not getting the correct view. Try this to get the topmost root view.
public FREObject call(FREContext context, FREObject[] params)
{
View view = findViewById(android.R.id.content).getRootView();
view.setDrawingCacheEnabled(true);
Bitmap image = view.getDrawingCache();
if(image == null)
{
System.out.println("Image returned was null!");
}
}
I also removed the buildDrawingCache() line; that can sometimes cause issues, and from what I've read it's not completely necessary.
Finally you'll want to check if the bitmap being returned is null. If so that could be why it's all black.
You can take a screenshot like this and save it to the SD card:
View content = findViewById(R.id.layoutroot);
content.setDrawingCacheEnabled(true);
Function to get the rendered view:
private void getScreen()
{
View content = findViewById(R.id.layoutroot);
Bitmap bitmap = content.getDrawingCache();
File file = new File( Environment.getExternalStorageDirectory() + "/asdf.png");
try
{
file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
bitmap.compress(CompressFormat.PNG, 100, ostream);
ostream.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
You have to add this permission to your AndroidManifest (if you want to save it):
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
I'd like to customized the size of the image used to cover up the real image to be displayed. In the UIL(Universal-Image-Loader) config, we can have .showStubImage(R.drawable.temp_drawable) as a display option.
My problem is, I am implementing a pinterest like view. By the time I scroll from the images, there is this unstable positions of the images because they are still being downloaded and covered up by a temp drawable. For example, the temporary drawable is 45 X 45, then the image to be displayed is 100 x 50. By the time the real image is showed there is this displacement effect of the images while scrolling because the temp image being replaced by the real one. Is there any way that we can detect the real image height and width to be displayed while is it still being downloaded, and using the width and height this can be used by the temp image to temporarily display the image size?
options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.ic_stub)
.showImageForEmptyUri(R.drawable.ic_empty)
.showImageOnFail(R.drawable.ic_error)
.cacheInMemory(true)
.cacheOnDisc(true)
imageLoader.displayImage(imageUrls[position], hold.image, options);
Update Code from the Universal-Image-Loader.jar
public void displayImage(String uri, ImageView imageView, DisplayImageOptions options, ImageLoadingListener listener) {
checkConfiguration();
if (imageView == null) {
throw new IllegalArgumentException(ERROR_WRONG_ARGUMENTS);
}
if (listener == null) {
listener = emptyListener;
}
if (options == null) {
options = configuration.defaultDisplayImageOptions;
}
if (TextUtils.isEmpty(uri)) {
engine.cancelDisplayTaskFor(imageView);
listener.onLoadingStarted(uri, imageView);
if (options.shouldShowImageForEmptyUri()) {
imageView.setImageResource(options.getImageForEmptyUri());
} else {
imageView.setImageDrawable(null);
}
listener.onLoadingComplete(uri, imageView, null);
return;
}
ImageSize targetSize = ImageSizeUtils.defineTargetSizeForView(imageView, configuration.maxImageWidthForMemoryCache, configuration.maxImageHeightForMemoryCache);
String memoryCacheKey = MemoryCacheUtil.generateKey(uri, targetSize);
engine.prepareDisplayTaskFor(imageView, memoryCacheKey);
listener.onLoadingStarted(uri, imageView);
Bitmap bmp = configuration.memoryCache.get(memoryCacheKey);
if (bmp != null && !bmp.isRecycled()) {
if (configuration.writeLogs) L.d(LOG_LOAD_IMAGE_FROM_MEMORY_CACHE, memoryCacheKey);
if (options.shouldPostProcess()) {
ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageView, targetSize, memoryCacheKey, options, listener, engine.getLockForUri(uri));
ProcessAndDisplayImageTask displayTask = new ProcessAndDisplayImageTask(engine, bmp, imageLoadingInfo, options.getHandler());
engine.submit(displayTask);
} else {
options.getDisplayer().display(bmp, imageView, LoadedFrom.MEMORY_CACHE);
listener.onLoadingComplete(uri, imageView, bmp);
}
} else {
if (options.shouldShowStubImage()) {
imageView.setImageResource(options.getStubImage());
} else {
if (options.isResetViewBeforeLoading()) {
imageView.setImageDrawable(null);
}
}
ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageView, targetSize, memoryCacheKey, options, listener, engine.getLockForUri(uri));
LoadAndDisplayImageTask displayTask = new LoadAndDisplayImageTask(engine, imageLoadingInfo, options.getHandler());
engine.submit(displayTask);
}
}
I like to have `.showStubImage(getImageDimension())'
Additional
new DownloadFilesTask().execute(imageUrls[position]);
private class DownloadFilesTask extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
URL uri = null;
try {
uri = new URL(params[0].toString());
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
InputStream in=null;
try
{
//URL oracle = new URL(url);
URLConnection urlConnection = uri.openConnection();
in = new BufferedInputStream(urlConnection.getInputStream());
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in , null, options);
//return options;
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
if(in!=null)
IoUtils.closeSilently(in);
}
return null;
}
}
This is not really related to Android. It's about design of your app.
If it's your server, you should decide on the sizes of the images and how to manage them, and put the correct placeholder accordingly.
If it's not your server, you can't know the size of the images without contacting the server in any way, so you will either have to set a static size that images will fit into, or get the sizes of the images before even showing the placeholders.
getting the image resolution is done with server files the same way as with other files, using inJustDecodeBounds while decoding.
EDIT:here's a sample code of how to get the size of a bitmap from the internet:
public static BitmapFactory.Options getBitmapOptions(final String url)
{
InputStream in=null;
try
{
URLConnection urlConnection = url.openConnection();
in = new BufferedInputStream(urlConnection.getInputStream());
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in , null, options);
return options;
}
finally
{
if(in!=null)
IOUtils.closeQuietly(in);
}
return null;
}
Usually you are allowed to give only resource id as per the library like below.
options = new DisplayImageOptions.Builder().showStubImage(R.drawable.stubImage)....
If at all you need to put your dynamically changing sized stub image, you need to tweak in the source code such that your options should accept sized bitmap rather than int. To do that I have just looked into the source code. Below are the steps:
Fist thing you need to do is to include it as library project instead of adding .jar in the libs folder.
In the ImageLoader class and then in the public void displayImage(String uri, ImageView imageView, DisplayImageOptions options, ImageLoadingListener listener) method, replace this line imageView.setImageResource(options.getImageForEmptyUri()); with imageView.setImageBitmap(sizedBitmap);
In the showStubImage(int stubImageRes) in DisplayImageOptions class, change the paramater as Bitmap and do necessary changes in that class.
Take care of all the things that need to be changed at where this feature gets reflected in different parts.
Changing the size of Bitmap:
Bitmap icon = BitmapFactory.decodeResource(context.getResources(),
R.drawable.stub_image);
bitmap = Bitmap.createScaledBitmap(stub, width, height, false);