Xamarain Android ImageView flashes black when updating quickly - android

So I have an imageview which I use setImageBitmap(pic) about about 30fps as a form of video stream, and the imageview image (not the rest of the screen) flashes black or disappears every few seconds. Is there a special setting to the imageview I need to add or disable in order to make it not go blank or flicker? I tried setting the imageview image, the layout's background image, VideoView, and all of them flicker black every few seconds while I update the background image. Any fix?
The image is about 320px wide and im not sure how tall, less than 320 tho.
Code doesn't really seem necessary, but this is all im doing ('imageStream' is the ImageView):
RunOnUiThread (() => StreamActivity.imageStream.SetImageBitmap(pic));
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/imageViewStream"
android:focusable="false"
android:focusableInTouchMode="false"
android:soundEffectsEnabled="false"
android:clickable="false"
android:longClickable="false"
android:hapticFeedbackEnabled="false"
android:adjustViewBounds="true"
android:cropToPadding="true" />
EDIT: I tried setting to software layer type, hardware layer type, and setting background color to Color.Argb(1, 0, 0, 0)
None of that worked.
EDIT: I seem to have fixed it by setting the application to run as hardware accelerated, and also the imageview and layout as hardware accelerated.
Then i changed my image setting code to
Bitmap tempBitmap = Bitmap.CreateBitmap(pic.Width, pic.Height, Bitmap.Config.Rgb565);
Canvas tempCanvas = new Canvas(tempBitmap); // then draw to the Canvas.
tempCanvas.DrawBitmap(pic, 0, 0, null);
RunOnUiThread (() => StreamActivity.imageStream.SetImageDrawable(new BitmapDrawable(tempBitmap)));

i thnk its because of RunOnUiThread.
if just want to change image in imageview jst use
ImageView.setBackgroundResource(R.drawable.thumbs_down);

I seem to have fixed it by setting the application to run as hardware accelerated, and also the imageview and layout as hardware accelerated.
Then i changed my image setting code to
Bitmap tempBitmap = Bitmap.CreateBitmap(pic.Width, pic.Height, Bitmap.Config.Rgb565);
Canvas tempCanvas = new Canvas(tempBitmap); // then draw to the Canvas.
tempCanvas.DrawBitmap(pic, 0, 0, null);
RunOnUiThread (() => StreamActivity.imageStream.SetImageDrawable(new BitmapDrawable(tempBitmap)));
and in my OnCreate()
imageStream.SetLayerType(LayerType.Hardware, null);
frameLayout1.SetLayerType(LayerType.Hardware, null);
and in my androidmanifest:
<application
android:label="MyName"
android:hardwareAccelerated="true"/>

I got around this by creating a BitmapDrawable from the bitmap OFF the UI thread, then calling SetImageDrawable ON the UI thread, then disposing of the BitmapDrawable.
I don't know why this works but I guess there is some overhead taken care of when creating the drawable that lightens the load on the draw routine.
I'm using Xamarin but you get the idea (the eventArgs.Frame is an Android Bitmap):
_stream.NewFrame += (object sender, NewFrameEventArgs eventArgs) =>
{
var bd = new BitmapDrawable(eventArgs.Frame);
(Context as Activity).RunOnUiThread(() =>
{
SetImageDrawable(bd);
bd.Dispose();
});
};

Related

How to make view.getDrawingCache() preserving transparency

If I have a view with a transparent background and I do bitmap = view.getDrawingCache();, that bitmap is unfortunately no more transparent. A black background is set in background.
I have even tried
view.setDrawingCacheBackgroundColor(Color.TRANSPARENT);
without success.
Actually this method allows to set the background color without any alpha support, Color.TRANSPARENT which is 0x00000000 is actually black if you don't care about the alpha part...
If I use Color.RED, the background is indeed very red.
Any idea to make this work? Is this a limitation of current Android API? Can I use draw() instead? but it's less performant that this view.getDrawingCache() I suppose (no cache)?
Thanks
I also get image with black background by calling getDrawingCache() method. Actually, the image has transparent background. Mistake is saving the image in jpeg format, so the gallery app shows transparent pixels in black color.
If you put it as an overlay, it'll work perfectly. There is no issue here.
Draw caching is somewhat of a relic of pre-HW-accelerated Android, so some stuff might be a bit confusing/not as well documented.
Transparency should work just fine as long as you leave out View#setDrawingCacheBackgroundColor(int) as this might cause the cache to drop down to 16 bit color space (see View#mDrawingCacheBackgroundColor).
This code
view.setDrawingCacheEnabled(true);
// wait for first layout
...
Bitmap b = view.getDrawingCache();
should give you an ARGB_8888 bitmap with transparent background. (You can also this in the Android Studio debugger by settings a breakpoint after the get call and 'View Bitmap' on the variable.
Try this code after setting the layout background color transparent in XML file
layout.setDrawingCacheEnabled(true);
Bitmap bmp = layout.getDrawingCache();
File mFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "smiley1.png");
FileOutputStream outStream;
outStream = new FileOutputStream(mFile);
bmp.compress(Bitmap.CompressFormat.PNG, 100, outStream);

How to remove a drawn bitmap in android?

In my program, the right tube is drawn first, after that the left one is drawn too
my goal is how to remove (Clear / Hide ... ) the first drawn tube, and keep only the second one
NB : I have already checked many topics related to the canvas Drawing, but nothing works
Picture : http://i.stack.imgur.com/6lofs.png
My Method :
protected void onDraw(Canvas cv) {
Bitmap haut = BitmapFactory.decodeResource(getResources(), R.drawable.haut);
cv.drawBitmap(haut, 300, 0, null);
// WHAT SHOULD I ADD HERE TO CLEAR THE FIRST TUBE
cv.drawBitmap(haut, 0, 0, null);
}
Thanks
You can create another empty bitmap and assign it to the related image view.
it will remove the first Bitmap:
ImageView iv = findViewById(R.id.your_imageview_id);
Bitmap bmp = Bitmap.createBitmap(0 , 0 , Bitmap.Config.ARGB_8888);
iv.setImageBitmap(bmp);
iv.invalidate();
You need to redraw the background and draw just one tube. No way to 'hide' it from drawn canvas unless it is not in separate view.
You need to draw all the same images again excluding the first image and then call invalidate() which will call onDraw(). When you work at low level drawings in canvas, you need to redraw everything for each change and invalidate..

RemoteViews (Widget) has fuzzy text when using a Bitmap

To place a custom font on my widget I am creating a bitmap with the font inside of it, and then placing that bitmap into my RemoteViews. However the text on the bitmap is pretty fuzzy, and looks really pixelated compared to how crystal clear it is within an Activity.
There are quite a few apps already that use custom fonts on a widget. I haven't found a solid way to do this yet though. If anyone has a better solution to this problem I would love to hear it!
Right now this is what I am using to create the bitmap and place it on the widget:
RemoteViews widgetView = new RemoteViews(this.getPackageName(), R.layout.widget);
widgetView.setImageViewBitmap(R.id.widgetImage, buildBitmap());
with
public Bitmap buildBitmap() {
Bitmap bitmap = Bitmap.createBitmap(160, 84, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
TextPaint textPaint = new TextPaint(TextPaint.LINEAR_TEXT_FLAG | TextPaint.ANTI_ALIAS_FLAG);
textPaint.setTypeface(getFont());
textPaint.setStyle(Style.FILL);
textPaint.setColor(fontColor);
textPaint.setTextSize(fontSize);
StaticLayout staticLayout = new StaticLayout(textString, textPaint, bitmap.getWidth(), Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
staticLayout.draw(canvas);
return bitmap;
}
The culprit Widgets! The one on the top is with the custom font, the middle image is with the default Sans font on a bitmap, to show that the text is fuzzy no matter what font is used.
The Last image is what the text looks like when using the default remoteView.setTextViewText("Text"); instead of a bitmap.
Any assistance on this problem would be greatly appreciated!
You can't assume 160x84. That's a very small size. When scaled it will likely be fuzzy as you can see. Instead, you'll want to actually measure out the bitmap size based on measurements of your text at a given sp. Paint.measureText is useful sometimes for these kinds of things to get the width, but you'll need height as well to do it right, so getTextBounds might be more useful. You'll probably need to add some padding too, but this should get you started. As you can see in your pictures, the clarity is not the only problem you have to deal with. You'll have to figure out word wrapping too (perhaps here is where Paint.measureText will come in handy).
The ImageView you are using requires android:scaleType="matrix" attribute to be added. Edit your widget layout xml and add that attribute where needed. The ImageView will then not try and scale your image to fit the view.
As previous posts have said your pixel dimensions are wrong. You should be maintaining a record of the size of each of your widgets so you can later use it for creating the bitmap.
If you want help working this bit out I can post some code. Accept this answer and post another about that question specifically and I will answer there with the code.

Android: How to to set imageView as a marker in google map API android?

till now i was using drawable to populate marker on my map .Now i was wondering it would be cool if i could display custom imageview as a marker in map.
till now i am doing it like
itemized= new Itemazide(drawable, mContext);
i want to achieve something like
I might be a bit late but I'll post a solution for others who have faced/are facing a similar issue. So basically what you have to do (at least for the solution you are seeking, i.e a custom image imposed on a box-like background) is impose the customImage on the background box with the help of a canvas. Using this implementation you can effectively create a BitmapDrawable from the canvas that you can then assign as a marker for your 'Overlay' / 'ItemizedOverlay'.
Also, please refrain from creating an ImageView for each overlay as this will utterly destroy your memory/ your app if you have to deal with thousands of such ImageViews simultaneously. Instead, use BitmapDrawables that can be assigned to the overlays during their construction and don't consume nearly enough memory as an ImageView.
public BitmapDrawable imageOnDrawable(int drawableBackground, Bitmap customImage)
{
//The following line is optional but I'd advise you to minimize the size of
//the size of the bitmap (using a thumbnail) in order to improve draw
//performance of the overlays (especially if you are creating a lot of overlays).
Bitmap customImageThumbnail = ThumbnailUtils.extractThumbnail(
customImage, 100, 100);
Bitmap bm = BitmapFactory.decodeResource(getResources(), drawableId);
bm = Bitmap.createScaledBitmap(bm, 112, 120, false);
Canvas canvas = new Canvas(bm);
canvas.drawBitmap(bm, 0, 0, null);
// The 6,6 in the below line refer to the offset of the customImage/Thumbnail
// from the top-left corner of the background box (or whatever you want to use
// as your background)
canvas.drawBitmap(customImageThumbnail, 6, 6, null);
return new BitmapDrawable(bm);
}
Yeah I was wondering if I could do something like this, i.e. show a custom View instead of drawable. You can override draw() method, but unfortunately it always (someone please tell me I'm wrong) has to be drawable. I think it's because custom View would take too much memory.
That being said, depending on what you're trying to achieve it's probably possible to hack mapview-baloon library to achieve some similar effect.
EDIT:
Now that you've shown what you're trying to achieve I think you should override draw() in your OverlayItem and in this method inflate your ImageView. But I didn't try to do it this way, so there may be some drawbacks (I remember a SO thread on a similar matter that claimed, that it would interrupt all touch events on this OverlayItem).
In google mapv2, map-view ballon like functionality is provided by default.
Just, you have to write some lines for it :
private GoogleMap mapView;
if (mapView == null)
mapView = ((MapFragment) getFragmentManager().findFragmentById(
R.id.map_view)).getMap();
mapView.getUiSettings().setMyLocationButtonEnabled(false);
mapView.setMyLocationEnabled(true);
MarkerOptions markerDestinationOptions;
markerDestinationOptions = new MarkerOptions()
.position(latLngDestination) .icon(BitmapDescriptorFactory.fromResource(R.drawable.marker));
mapView.addMarker(markerDestinationOptions);

Android: how to simply draw a bitmap on another bitmap

I'm new to Android dev and I'm having a hard time trying to do something which seems obvious to me: drawing little images on top of a bigger image.
Let's say that I have a 500x500 image and I want to draw icons at different locations. Icons are png files that I load with:
Bitmap img =
BitmapFactory.decodeResource(getResources(),
R.drawable.idIcon1)
My "background image" is a LayerDrawable.
Then, I am totally lost... Do I have to create a canvas ? How to draw on my "background image" my icons at different positions?
int positionLeft=0;
int positionTop=0;
Bitmap newBitmap =Bitmap.createBitmap(backgroundBitmap.getWidth(),bitmap.getHeight(),Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(newBitmap);
canvas.drawBitmap(backgroundBitmap, positionLeft, positionTop,null);
positionLeft=100;
positionTop=100;
canvas.drawBitmap(iconBitmap,positionLeft,positionTop,null);
imageView.setImageBitmap(newBitmap);
You're making simple things difficult. Just use a layout with android:background attribute, and then add ImageViews dynamically with the necessary bitmaps inside.

Categories

Resources