long time reader, first time asker so please be gently ;)
I have an Android code that displays around 10 pictures in second on ImageView.
(calling setImageBitmap on ImageView to set new bitmap)
This causes display lags so I'm trying to speed it as much as I can.
I found that (with traceview) that app spend a lot of time on methods:
ViewRoot.performTraversals
View.measure
FrameLayout.onmeasure
ViewGrou.measureChildWithMargins
I suspecting on ImageView measuring so i have create CustomImageView and overide onMeasure just to call super method and write sysout.
It seems that after every setImageBitmap onmeasure is called 3 times.
Bitmaps are allways of the same size so there is no change. Actually it can be change from time to time when image source is changed but that should be remeasured only then.
What can I change, overide, do to eliminite this measurement impact on application speed?
If you need further information tell me and I will provide it.
Sample code
final Bitmap bitmapScaled = Bitmap.createScaledBitmap(bitmap2, width, height, false);
imageView2.setScaleType(ScaleType.CENTER_INSIDE);
if (setSize) {
setSize(imageView2, width, height);
}
imageView2.setImageBitmap(bitmapScaled);
Method that I change to make it work faster (possibly not safe?!)
boolean layout=true;
int noL=1;
#Override
public void requestLayout() {
if (layout){
super.requestLayout();
if (noL>10){
layout=false;
}else{
noL++;
}
}
}
When I had a similar problem I did the following:
public class ImageViewEx extends ImageView{
private boolean makeRequest;
public ImageViewEx(Context context){
super(context);makeRequest=true;
}
public ImageViewEx(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ImageViewEx(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
makeRequest=true;
}
public void setImageBitmapNoRequestLayout(Bitmap bitmap) {
makeRequest = false;
setImageBitmap(bitmap);
makeRequest = true;
}
#Override public void requestLayout(){
if(makeRequest)super.requestLayout();
}
}
Now changing the bitmap with setImageBitmapNoRequestLayout(...) does not call requestLayout().
Related
My Question is about loading image into image View With Glide. I Know How to Load Image With Glide. But I want to Create a custom ImageView so that It can Load Images By Default With Glide (To make it faster and remove memory issues by default). Is It Possible. If Yes Then How? Thank you in advance.
public class CustomImageView extends ImageView {
public CustomImageView(Context context) {
super(context);
}
///How to Over Ride Back Ground Attribute Sent by XML / Sent By Java Initialization
Glide.with(context).load(R.drawable.chains).into(this);
}
Update:
To be very simple I want To Use My Custom ImageView in my whole project Instead of Ordinary one. so that it will over come memory issues by default. In CustomImageView I want to Load Images with Glide . I'm Looking something Like
public class CustomImageView extends ImageView {
public CustomImageView(Context context) {
super(context);
}
///How to Over Ride Back Ground Attribute Sent by XML / Sent By Java Initialization
#Override
public void setBackground(Drawable background) {
super.setBackground(background);
Glide.with(this.getContext()).load(background).into(this);
}
}
how to manage CustomImageView to work exactly like ImageView but Instead load Images With Glide.
Try something like this:
public class CustomImageView extends android.support.v7.widget.AppCompatImageView {
public CustomImageView(Context context) {
super(context);
}
public CustomImageView(Context context, #Nullable AttributeSet set) {
super(context, set);
int[] attrs = {android.R.attr.background};
TypedArray typedArray = context.obtainStyledAttributes(set, attrs);
Drawable drawable = typedArray.getDrawable(0); // 0 is an index of attrs[]
if (drawable != null) {
setBackground(null);
Glide.with(context).load(typedArray.getResourceId(0, placeholder_resource_id)).into(this); // 0 is an index of attrs[]
}
typedArray.recycle();
}
}
I'm trying to create a custom LinearLayout that can rotate all children in the layout by a set angle. That is, I want to rotate the entire canvas and the children, not the children individually.
I need to support API Level 10, so android:rotate which was introduced in API Level 11 will not help me here.
I've been looking around and think I need to do something along the lines of this code below, but with this code nothing gets rotated.
Any ideas on what I'm missing here?
public class RotationLayout extends LinearLayout {
public RotationLayout(Context context) {
super(context);
init();
}
public RotationLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public RotationLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
setWillNotDraw(false);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.save();
canvas.rotate(350,0,0);
super.onDraw(canvas);
canvas.restore();
}
}`
I tried your code with a few changes.
In the onCreate(Bundle) of an activity class, I initialized the RotationLayout:
RotationLayout rl = new RotationLayout(this);
ImageView iv = new ImageView(this);
iv.setImageDrawable(getResources().getDrawable(R.drawable.some_drawable));
rl.addView(iv);
setContentView(rl);
And the view was indeed rotated 350 degrees(or 10 degrees counter-clockwise) around (0,0). This was what I changed:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.rotate(350,0,0);
}
From notes on Canvas.save() (Link):
Saves the current matrix and clip onto a private stack. Subsequent
calls to translate,scale,rotate,skew,concat or clipRect,clipPath will
all operate as usual, but when the balancing call to restore() is
made, those calls will be forgotten, and the settings that existed
before the save() will be reinstated.
I want to create a banner in Android with two different images in one ImageView, every 5 seconds the images should alternate one after the other.
use 2 imageviews,and set images to that imageview and bydefault make imageview2 as gone after 5 seconds make imagevew1 as gone and imageview2 as visible and viceversea for every 5 sec
Create a custom View like so:
public static class MyBannerView extends View
{
private int width;
private int height;
private Bitmap bitmap;
public RenderView(Context context)
{
super(context);
init();
}
public RenderView(Context context, AttributeSet attrs)
{
super(context, attrs);
init();
}
public RenderView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init()
{
//anything you might need here
}
//This method is called when the View changes size like on rotation
protected void onSizeChanged (int w, int h, int oldw, int oldh)
{
width = w; //this will let you keep track of width and height should you need it.
height = h;
}
protected void updateMyBanner(Bitmap b)
{
bitmap = b;
invalidate(); // This will force your view to redraw itself;
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//there are four different methods for drawBitmap pick the one that
// suites your needs the best
canvas.drawBitmap(params which will include bitmap)
}
}
Now you place this view in your layout in some way and you will call updateMyBanner(Bitmap b) with your bitmap every 5 seconds or whatever. You can create an AsyncTask to handle this, or you can use a Handler object and create a Runnable which will call that.
It is important to remember that you can only touch the UI through the main activity thread, so if you chose to use a thread for this, you will need to use a Handler on the main thread to actually preform the update.
I want to be able to mirror my app so it can be viewed in the windshield of a vehicle.
My XML has several nested LinearLayouts, TextViews and ImageViews. Currently I'm transforming each one and although it is mirrored, the structure of the elements is not (what was at the top is now at the bottom).
I've been looking for days and so far have tried a couple of approaches that have failed.
An animation that uses a matrix to flip on the X axis kind of works, except that it either reverts back or it stays and doesn't update, which is no good for interacting with the app.
I just tried to create a custom LinearLayout extending the parent one, hoping that I could apply a Matrix in its onDraw() method but that gives me a blank screen (I had to set setWillNotDraw(false); to hit the onDraw()).
Well eventually I found a solution that works well for me (so far it's caused no issues for users).
My solution was to override dispatchDraw to scale the canvas in my custom LinearLayout. Then I just needed to flip the touch events by overriding dispatchTouchEvent:
public class CustomContainer extends LinearLayout {
public CustomContainer(Context context) {
super(context);
this.setWillNotDraw(false);
}
public CustomContainer(Context context, AttributeSet attrs) {
super(context, attrs);
this.setWillNotDraw(false);
}
public CustomContainer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.setWillNotDraw(false);
}
#Override
protected void dispatchDraw(Canvas canvas) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
// Flip the view canvas
if (MyHUDActivity.mHUDMode) canvas.scale(1,-1, getWidth(), getHeight()/2f);
super.dispatchDraw(canvas);
canvas.restore();
}
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
// If in HUD mode then flip the touch zones
if (MyHUDActivity.mHUDMode) event.setLocation(event.getX(), getHeight()-event.getY());
return super.dispatchTouchEvent(event);
}
}
You can use the new Animation api to deal with reverting back after the horizontal flip.
I am trying to use the RotationAnimation to move an ImageButton. I have extended ImageButton to override onAnimationEnd to avoid the screen flicker at the end of the animation, and would like to update the position of the actual button [since the animation is just a superficial move]. How can I determine the exact coordinates of the button at the end of the animation? Attached is some of my code..
public class HomeNavigationButton extends ImageButton {
public HomeNavigationButton(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
public HomeNavigationButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public HomeNavigationButton(Context context) {
super(context);
}
#Override
protected void onAnimationEnd() {
super.onAnimationEnd();
int l = ?
int t = ?
int r = ?
int b = ?
this.layout(l,t,r,b);
}
The position of the button animation? I would go out on a limb and guess you can't. Animations are interesting. They're not "real". Think of them as a mirage. Try this. Rotate the image VERY slowly. If the image is a rectangle, when the image is about 45 degrees, click where the image used to be, but is no long. You'll actually register a click, because the image isn't actually being rotate in real coordinates.
I would consider actually animating the button like a game sprite, or do some trial and error with the animation and set values manually. If you do the second one, make sure you dynamically convert to DIP coordinates rather than raw ints.