Showing posts with label android-imageview. Show all posts
Showing posts with label android-imageview. Show all posts

Tuesday, December 5, 2017

passing value from activity to view class

Leave a Comment

EDIT - I don't necessarily want to use the exact same code. All I want is to change paint color when a checkbox is selected to be able to draw on an image view. Any other approach is welcome.

I did go through related questions but couldn't get the answer. Please help instead of down-voting. I have an activity in which there are 3 checkboxes in different views. These checkboxes are to pick up a color. In the DrawingView class, I have to draw on my canvas with the color that is checked. What I want is to pass an integer value from the activity to the view class and set the color of paint accordingly. itried using getter and setters, but I get black color. I suppose this is because the color is being set in the constructor itself, and it does not change when I check any box.

Edit- Please refer this for updates in the below code

Code: MainActivity- the color/checkbox is selected here. And the drawing is to be done in the layout of this activity itself.

        carImageView.setOnTouchListener(new View.OnTouchListener() {         @Override         public boolean onTouch(View view, MotionEvent motionEvent) {             drawingView=new DrawingView(carImageView.getContext());             drawingView=new DrawingView(carImageView.getContext(),null);             drawingView.setColor(color);             return false;         }     });     scratchesCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {       @Override       public void onCheckedChanged(CompoundButton compoundButton, boolean b) {           if(b)           {               color=1;               chipsCb.setChecked(false);               dentsCb.setChecked(false);           }       }   });     chipsCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {         @Override         public void onCheckedChanged(CompoundButton compoundButton, boolean b) {             if(b)             {                 color=2;                 scratchesCb.setChecked(false);                 dentsCb.setChecked(false);             }         }     });     dentsCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {         @Override         public void onCheckedChanged(CompoundButton compoundButton, boolean b) {             if(b)             {                 color=3;                 chipsCb.setChecked(false);                 scratchesCb.setChecked(false);             }         }     }); } 

View Class-

   public DrawingView(Context context, @Nullable AttributeSet attrs) {    super(context, attrs);     mPaint=new Paint();     if(color==1)         mPaint.setColor(Color.RED);     else if(color==2)         mPaint.setColor(Color.BLUE);     else if(color==3)         mPaint.setColor(Color.GREEN);     this.context=context;     mPath=new Path();     mPaint.setAntiAlias(true);     mPaint.setStyle(Paint.Style.STROKE);     mPaint.setStrokeJoin(Paint.Join.MITER);     mPaint.setStrokeWidth(5f); }      public void setColor(int color){     this.color=color; } public int getColor(){     return this.color; } 

5 Answers

Answers 1

In the MainActivity, you are creating a DrawingView that has no relationship to your image view that is displayed. So, when you change the color, you are not changing the color of the displayed image view but of the unconnected DrawingView. The image view never has a new color defined and always defaults to black.

Here is a video of a small working app based upon your most recently supplied code. Maybe all the colors shouldn't change when a new check box is clicked, but you will be able to address that issue separately.

Changes I have made to the Java code are commented as such. Changes were also made to the XML to allow your code to run in my environment, but those changes were not commented.

enter image description here

MainActivity.java (Updated)

public class MainActivity extends AppCompatActivity {     ImageView caricon;     int itemSelected = 0;     private DrawingView carImageView;     Bitmap bitmap;     ImageView backarrow;     TextView nextcheckinAB2;     Bitmap bmp;     public static int color;     CheckBox scratchesCb, chipsCb, dentsCb;      @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);         carImageView = (DrawingView) findViewById(R.id.carImageView);         scratchesCb = (CheckBox) findViewById(R.id.scratchesCheckBox);         chipsCb = (CheckBox) findViewById(R.id.ChipCheckbx);         dentsCb = (CheckBox) findViewById(R.id.DentsCheckBox);          // Change: Make sure to initialize the color         color = 1;         carImageView.setColor(color);          carImageView.setOnTouchListener(new View.OnTouchListener() {             @Override             public boolean onTouch(View view, MotionEvent motionEvent) {                 // drawingView = new DrawingView(carImageView.getContext(),null);                 carImageView.setColor(color);                 return false;             }         });           scratchesCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {             @Override             public void onCheckedChanged(CompoundButton compoundButton, boolean b) {                 if (b) {                     color = 1;                     carImageView.clearCanvas();                     carImageView.setColor(1); //                     chipsCb.setChecked(false);                     dentsCb.setChecked(false);                 }             }         });         chipsCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {             @Override             public void onCheckedChanged(CompoundButton compoundButton, boolean b) {                 if (b) {                     color = 2;                     carImageView.setColor(2);                     scratchesCb.setChecked(false);                     dentsCb.setChecked(false);                  }             }         });         dentsCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {             @Override             public void onCheckedChanged(CompoundButton compoundButton, boolean b) {                 if (b) {                     color = 3;                     // Change: Do like the other check boxes althogh not really needed.                     carImageView.setColor(3);                     chipsCb.setChecked(false);                     scratchesCb.setChecked(false);                  }             }         });     } } 

DrawingView.java (Updated)

public class DrawingView extends android.support.v7.widget.AppCompatImageView {     private Path mPath;     private Paint mPaint;     private float mX, mY;     private static final float TOLERANCE = 5;     int color;     Context context;      public DrawingView(Context context) {         super(context);         this.context = context;         init();     }      public DrawingView(Context context, @Nullable AttributeSet attrs) {         super(context, attrs);         this.context = context;         init();       }      public void init() {         mPath = new Path();         mPaint = new Paint();         mPaint.setStyle(Paint.Style.STROKE);         mPaint.setStrokeJoin(Paint.Join.MITER);         mPaint.setStrokeWidth(5f);     }      @Override     protected void onSizeChanged(int w, int h, int oldw, int oldh) {         super.onSizeChanged(w, h, oldw, oldh);     }      @Override     protected void onDraw(Canvas canvas) {         super.onDraw(canvas);         canvas.drawPath(mPath, mPaint);     }      public void setColor(int color) {         if (color == 1) {             mPaint.setColor(Color.RED);             this.color = color;             invalidate();         } else if (color == 2) {             mPaint.setColor(Color.BLUE);             this.color = color;             invalidate();         } else if (color == 3) {             mPaint.setColor(Color.GREEN);             this.color = color;             invalidate();         }      }      public int getColor() {         return this.color;     }      private void onStartTouch(float x, float y) {         mPath.moveTo(x, y);         mX = x;         mY = y;     }      private void moveTouch(float x, float y) {         float dx = Math.abs(x - mX);         float dy = Math.abs(y - mY);         if (dx >= TOLERANCE || dy >= TOLERANCE) {             mPath.quadTo(mX, mY, (mX + x) / 2, (mY + y) / 2);             mX = x;             mY = y;         }     }      public void clearCanvas() {         mPath.reset();         mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));         invalidate();     }      private void upTouch() {         mPath.lineTo(mX, mY);     }      @Override     public boolean onTouchEvent(MotionEvent event) {         float x = event.getX();         float y = event.getY();         switch (event.getAction()) {             case MotionEvent.ACTION_DOWN:                 onStartTouch(x, y);                 invalidate();                 break;             case MotionEvent.ACTION_MOVE:                 moveTouch(x, y);                 invalidate();                 break;             case MotionEvent.ACTION_UP:                 upTouch();                 invalidate();                 break;         }          return true;      } } 

activity_main.xml (Updated)

    <LinearLayout         android:layout_width="match_parent"         android:layout_height="wrap_content"         android:layout_marginLeft="5dp"         android:layout_marginRight="5dp"         android:orientation="horizontal"         android:weightSum="3">          <HorizontalScrollView             android:id="@+id/horizontalSrollView"             android:layout_width="wrap_content"             android:layout_height="wrap_content"             android:layout_weight="1">              <LinearLayout                 android:layout_width="wrap_content"                 android:layout_height="wrap_content"                 android:orientation="horizontal">                  <RelativeLayout                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:layout_marginLeft="5dp"                     android:layout_weight="1">                      <LinearLayout                         android:layout_width="wrap_content"                         android:layout_height="wrap_content"                         android:layout_marginTop="5dp"                          android:orientation="vertical">                          <LinearLayout                             android:layout_width="wrap_content"                             android:layout_height="wrap_content"                             android:orientation="horizontal"                             android:paddingLeft="15dp"                             android:paddingRight="15dp"                             android:paddingTop="5dp"                             android:weightSum="2">                              <ImageView                                 android:layout_width="20dp"                                 android:layout_height="20dp"                                 android:layout_marginRight="2dp"                                 android:layout_weight="0.5"                                 android:background="@android:color/holo_red_light" />                              <TextView                                 android:layout_width="wrap_content"                                 android:layout_height="wrap_content"                                 android:layout_marginLeft="2dp"                                 android:layout_weight="1.5"                                 android:text="Scratches"                                 android:textColor="#000" />                         </LinearLayout>                          <CheckBox                             android:id="@+id/scratchesCheckBox"                             android:layout_width="wrap_content"                             android:layout_height="wrap_content"                             android:layout_gravity="center"                             android:checked="true" />                     </LinearLayout>                  </RelativeLayout>                  <RelativeLayout                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:layout_weight="1">                      <LinearLayout                         android:layout_width="wrap_content"                         android:layout_height="wrap_content"                         android:layout_marginTop="5dp"                         android:orientation="vertical">                          <LinearLayout                             android:layout_width="wrap_content"                             android:layout_height="wrap_content"                             android:orientation="horizontal"                             android:paddingLeft="15dp"                             android:paddingRight="15dp"                             android:paddingTop="5dp"                             android:weightSum="2">                              <ImageView                                 android:layout_width="20dp"                                 android:layout_height="20dp"                                 android:layout_marginRight="2dp"                                 android:layout_weight="0.5"                                 android:background="@android:color/holo_blue_light" />                              <TextView                                 android:layout_width="wrap_content"                                 android:layout_height="wrap_content"                                 android:layout_marginLeft="2dp"                                 android:layout_weight="1.5"                                 android:text="Chips"                                 android:textColor="#000" />                         </LinearLayout>                          <CheckBox                             android:id="@+id/ChipCheckbx"                             android:layout_width="wrap_content"                             android:layout_height="wrap_content"                             android:layout_gravity="center" />                     </LinearLayout>                  </RelativeLayout>                  <RelativeLayout                     android:layout_width="wrap_content"                     android:layout_height="wrap_content"                     android:layout_weight="1">                      <LinearLayout                         android:layout_width="wrap_content"                         android:layout_height="wrap_content"                         android:layout_marginTop="5dp"                         android:orientation="vertical">                          <LinearLayout                             android:layout_width="wrap_content"                             android:layout_height="wrap_content"                             android:orientation="horizontal"                             android:paddingLeft="15dp"                             android:paddingRight="15dp"                             android:paddingTop="5dp"                             android:weightSum="2">                              <ImageView                                 android:layout_width="20dp"                                 android:layout_height="20dp"                                 android:layout_marginRight="2dp"                                 android:layout_weight="0.5"                                 android:background="@android:color/holo_green_light" />                              <TextView                                 android:layout_width="wrap_content"                                 android:layout_height="wrap_content"                                 android:layout_marginLeft="2dp"                                 android:layout_weight="1.5"                                 android:text="Dings/Dents"                                 android:textColor="#000" />                         </LinearLayout>                          <CheckBox                             android:id="@+id/DentsCheckBox"                             android:layout_width="wrap_content"                             android:layout_height="wrap_content"                             android:layout_gravity="center" />                     </LinearLayout>                  </RelativeLayout>             </LinearLayout>          </HorizontalScrollView>      </LinearLayout>      <LinearLayout         android:layout_width="match_parent"         android:layout_height="match_parent"         android:layout_weight="8.7">          <[your package name].DrawingView             android:id="@+id/carImageView"             android:layout_width="200dp"             android:layout_height="200dp"             android:src="@mipmap/ic_launcher"             android:layout_gravity="center_vertical" />         <!--<ImageView             android:id="@+id/carImageView"             android:layout_width="match_parent"             android:layout_height="match_parent"             android:layout_gravity="center_vertical"/>-->     </LinearLayout>   </LinearLayout> 

Answers 2

you need change function setColor.

1.change mPaint color.

2.add invalidate() for redraw view.

public void setColor(int color){     this.color=color;      mPaint.setColor(color);     invalidate(); } 

Answers 3

You need to call invalidate() on the View to make it update.

Try this,

final DrawingView drawingView = new DrawingView(carImageView.getContext());  carImageView.setOnTouchListener(new View.OnTouchListener() {     @Override     public boolean onTouch(View view, MotionEvent motionEvent) {         drawingView.setColor(color);         return false;     } });   scratchesCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {   @Override   public void onCheckedChanged(CompoundButton compoundButton, boolean b) {       if(b)       {           color = 1;           drawingView.setColor(color);            chipsCb.setChecked(false);           dentsCb.setChecked(false);       }   } });  chipsCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {     @Override     public void onCheckedChanged(CompoundButton compoundButton, boolean b) {         if(b)         {             color = 2;             drawingView.setColor(color);              scratchesCb.setChecked(false);             dentsCb.setChecked(false);         }     } });   dentsCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {     @Override     public void onCheckedChanged(CompoundButton compoundButton, boolean b) {         if(b)         {             color = 3;             drawingView.setColor(color);              chipsCb.setChecked(false);             scratchesCb.setChecked(false);         }     } }); 

DrawingView.java

public DrawingView(Context context) {     super(context);     this.context = context;     init(); }  public DrawingView(Context context, @Nullable AttributeSet attrs) {     super(context, attrs);     this.context=context;     init(); }  private void init() {     mPath=new Path();      mPaint = new Paint();     mPaint.setAntiAlias(true);     mPaint.setStyle(Paint.Style.STROKE);     mPaint.setStrokeJoin(Paint.Join.MITER);     mPaint.setStrokeWidth(5f);     setColor(color); }   public void setColor(int color){     this.color=color;     if(color==1)         mPaint.setColor(Color.RED);     else if(color==2)         mPaint.setColor(Color.BLUE);     else if(color==3)         mPaint.setColor(Color.GREEN);      // Call invalidate     invalidate(); } 

Answers 4

Define static data member in your DrawingView

static int color = 1; //default

Then, from your activity simply call

DrawingView.color = someValue;

Static Keyword before variable color will make sure there is only one variable reference for all objects of your DrawingView class.

Answers 5

"even if I pass a static value, say 3 in main activity in drawingview.setColor(int) it gives black. This means the setColor function in Drawingview isn't working. "

Does this mean it will call paint.setColor(3) ?

If yes, this will of course turn your color black. Try passing Color.GREEN instead

Read More

Friday, June 24, 2016

How to animate ImageView from center-crop to fill the screen and vice versa (facebook style)?

Leave a Comment

Background

Facebook app has a nice transition animation between a small image on a post, and an enlarged mode of it that the user can also zoom to it.

As I see it, the animation not only enlarges and moves the imageView according to its previous location and size, but also reveals content instead of stretching the content of the imageView.

This can be seen using the next sketch i've made:

enter image description here

The question

How did they do it? did they really have 2 views animating to reveal the content?

How did they make it so fluid as if it's a single view?

the only tutorial i've seen (link here) of an image that is enlarged to full screen doesn't show well when the thumbnail is set to be center-crop.

Not only that, but it works even on low API of Android.

does anybody know of a library that has a similar ability?


EDIT: I've found a way and posted an answer, but it's based on changing the layoutParams , and i think it's not efficient and recommended.

I've tried using the normal animations and other animation tricks, but for now that's the only thing that worked for me.

If anyone know what to do in order to make it work in a better way, please write it down.

5 Answers

Answers 1

Ok, i've found a possible way to do it. i've made the layoutParams as variables that keep changing using the ObjectAnimator of the nineOldAndroids library. i think it's not the best way to achieve it since it causes a lot of onDraw and onLayout, but if the container has only a few views and doesn't change its size, maybe it's ok.

the assumption is that the imageView that i animate will take the exact needed size in the end, and that (currently) both the thumbnail and the animated imageView have the same container (but it should be easy to change it.

as i've tested, it is also possible to add zoom features by extending the TouchImageView class . you just set the scale type in the beginning to center-crop, and when the animation ends you set it back to matrix, and if you want, you can set the layoutParams to fill the entire container (and set the margin to 0,0).

i also wonder how come the AnimatorSet didn't work for me, so i will show here something that works, hoping someone could tell me what i should do.

here's the code:

MainActivity.java

public class MainActivity extends Activity {     private static final int IMAGE_RES_ID = R.drawable.test_image_res_id;     private static final int ANIM_DURATION = 5000;     private final Handler mHandler = new Handler();     private ImageView mThumbnailImageView;     private CustomImageView mFullImageView;     private Point mFitSizeBitmap;      @Override     protected void onCreate(final Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);         mFullImageView = (CustomImageView) findViewById(R.id.fullImageView);         mThumbnailImageView = (ImageView) findViewById(R.id.thumbnailImageView);         mHandler.postDelayed(new Runnable() {              @Override             public void run() {                 prepareAndStartAnimation();             }          }, 2000);     }      private void prepareAndStartAnimation() {         final int thumbX = mThumbnailImageView.getLeft(), thumbY = mThumbnailImageView.getTop();         final int thumbWidth = mThumbnailImageView.getWidth(), thumbHeight = mThumbnailImageView.getHeight();         final View container = (View) mFullImageView.getParent();         final int containerWidth = container.getWidth(), containerHeight = container.getHeight();         final Options bitmapOptions = getBitmapOptions(getResources(), IMAGE_RES_ID);         mFitSizeBitmap = getFitSize(bitmapOptions.outWidth, bitmapOptions.outHeight, containerWidth, containerHeight);          mThumbnailImageView.setVisibility(View.GONE);         mFullImageView.setVisibility(View.VISIBLE);         mFullImageView.setContentWidth(thumbWidth);         mFullImageView.setContentHeight(thumbHeight);         mFullImageView.setContentX(thumbX);         mFullImageView.setContentY(thumbY);         runEnterAnimation(containerWidth, containerHeight);     }      private Point getFitSize(final int width, final int height, final int containerWidth, final int containerHeight) {         int resultHeight, resultWidth;         resultHeight = height * containerWidth / width;         if (resultHeight <= containerHeight) {             resultWidth = containerWidth;         } else {             resultWidth = width * containerHeight / height;             resultHeight = containerHeight;         }         return new Point(resultWidth, resultHeight);     }      public void runEnterAnimation(final int containerWidth, final int containerHeight) {         final ObjectAnimator widthAnim = ObjectAnimator.ofInt(mFullImageView, "contentWidth", mFitSizeBitmap.x)                 .setDuration(ANIM_DURATION);         final ObjectAnimator heightAnim = ObjectAnimator.ofInt(mFullImageView, "contentHeight", mFitSizeBitmap.y)                 .setDuration(ANIM_DURATION);         final ObjectAnimator xAnim = ObjectAnimator.ofInt(mFullImageView, "contentX",                 (containerWidth - mFitSizeBitmap.x) / 2).setDuration(ANIM_DURATION);         final ObjectAnimator yAnim = ObjectAnimator.ofInt(mFullImageView, "contentY",                 (containerHeight - mFitSizeBitmap.y) / 2).setDuration(ANIM_DURATION);         widthAnim.start();         heightAnim.start();         xAnim.start();         yAnim.start();         // TODO check why using AnimatorSet doesn't work here:         // final com.nineoldandroids.animation.AnimatorSet set = new AnimatorSet();         // set.playTogether(widthAnim, heightAnim, xAnim, yAnim);     }      public static BitmapFactory.Options getBitmapOptions(final Resources res, final int resId) {         final BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();         bitmapOptions.inJustDecodeBounds = true;         BitmapFactory.decodeResource(res, resId, bitmapOptions);         return bitmapOptions;     }  } 

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:tools="http://schemas.android.com/tools"     android:layout_width="match_parent"     android:layout_height="match_parent"     tools:context=".MainActivity" >      <com.example.facebookstylepictureanimationtest.CustomImageView         android:id="@+id/fullImageView"         android:layout_width="0px"         android:layout_height="0px"         android:background="#33ff0000"         android:scaleType="centerCrop"         android:src="@drawable/test_image_res_id"         android:visibility="invisible" />      <ImageView         android:id="@+id/thumbnailImageView"         android:layout_width="100dp"         android:layout_height="100dp"         android:layout_alignParentBottom="true"         android:layout_alignParentRight="true"         android:scaleType="centerCrop"         android:src="@drawable/test_image_res_id" />  </RelativeLayout> 

CustomImageView.java

public class CustomImageView extends ImageView {     public CustomImageView(final Context context) {         super(context);     }      public CustomImageView(final Context context, final AttributeSet attrs) {         super(context, attrs);     }      public CustomImageView(final Context context, final AttributeSet attrs, final int defStyle) {         super(context, attrs, defStyle);     }      public void setContentHeight(final int contentHeight) {         final LayoutParams layoutParams = getLayoutParams();         layoutParams.height = contentHeight;         setLayoutParams(layoutParams);     }      public void setContentWidth(final int contentWidth) {         final LayoutParams layoutParams = getLayoutParams();         layoutParams.width = contentWidth;         setLayoutParams(layoutParams);     }      public int getContentHeight() {         return getLayoutParams().height;     }      public int getContentWidth() {         return getLayoutParams().width;     }      public int getContentX() {         return ((MarginLayoutParams) getLayoutParams()).leftMargin;     }      public void setContentX(final int contentX) {         final MarginLayoutParams layoutParams = (MarginLayoutParams) getLayoutParams();         layoutParams.leftMargin = contentX;         setLayoutParams(layoutParams);     }      public int getContentY() {         return ((MarginLayoutParams) getLayoutParams()).topMargin;     }      public void setContentY(final int contentY) {         final MarginLayoutParams layoutParams = (MarginLayoutParams) getLayoutParams();         layoutParams.topMargin = contentY;         setLayoutParams(layoutParams);     }  } 

Answers 2

Another solution, if you just want to make an animation of an image from small to large, you can try ActivityOptions.makeThumbnailScaleUpAnimation or makeScaleUpAnimationand see if they suit you.

http://developer.android.com/reference/android/app/ActivityOptions.html#makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int)

Answers 3

I found a way to get a similar affect in a quick prototype. It might not be suitable for production use (I'm still investigating), but it is quick and easy.

  1. Use a fade transition on your activity/fragment transition (which starts with the ImageView in exactly the same position). The fragment version:

    final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();     fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);     ...etc     

    The activity version:

    Intent intent = new Intent(context, MyDetailActivity.class); startActivity(intent); getActivity().overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); 

    This gives a smooth transition without a flicker.

  2. Adjust the layouts dynamically in the onStart() of the new fragment (you need to save member fields to the appropriate parts of your UI in onCreateView, and add some flags to ensure this code only gets called once).

    @Override     public void onStart() {         super.onStart();      // Remove the padding on any layouts that the image view is inside     mMainLayout.setPadding(0, 0, 0, 0);      // Get the screen size using a utility method, e.g.      //  http://stackoverflow.com/a/12082061/112705     // then work out your desired height, e.g. using the image aspect ratio.     int desiredHeight = (int) (screenWidth * imgAspectRatio);      // Resize the image to fill the whole screen width, removing      // any layout margins that it might have (you may need to remove      // padding too)     LinearLayout.LayoutParams layoutParams =             new LinearLayout.LayoutParams(screenWidth, desiredHeight);     layoutParams.setMargins(0, 0, 0, 0);      mImageView.setLayoutParams(layoutParams); }     

Answers 4

I think the easiest way is to animate the height of the ImageView (a regular imageview, not necessary a custom view) while keeping the scaleType to centerCrop until full height, which you can know in advance if you set the image height to wrap_content in your layout and then use a ViewTreeObserver to know when the layout has ended, so you can get the ImageView height and then set the new "collapsed" height. I have not tested it but this is how I would do it.

You can also have a look at this post, they do something similar http://nerds.airbnb.com/host-experience-android/

Answers 5

I'm not sure why everyone is talking about the framework. Using other peoples code can be great at times; but it sounds like what you are after is precise control over the look. By getting access to the graphics context you can have that. The task is pretty simple in any environment that has a graphics context. In android you can get it by overriding the onDraw method and using the Canvas Object. It has everything you need to draw an image at many different scales, positions and clippings. You can even use a matrix if your familiar with that type of thing.

Steps

  1. Make sure you have exact control of positioning, scale, and clip. This means disabling any layouts or auto-alignment that might be setup inside your objects container.

  2. Figure you out what your parameter t will be for linear interpolation and how you will want it to relate to time. How fast or slow, and will there be any easing. t should be dependent on time.

  3. After the thumbnails are cached, load the full scale image in the background. But don't show it yet.

  4. When the animation trigger fires, show the large image and drive your animation with your t parameter using interpolation between the initial properties' states to the final properties' states. Do this for all three properties, position, scale and clip. So for all properties do the following:

    Sinterpolated = Sinitial * (t-1)    +   Sfinal * t; // where //    t is between 0.0 and 1.0 //    and S is the states value //    for every part of scale, position, and clip // //    Sinitial is what you are going from //    Sfinal   is what you are going to //     //    t should change from 0.0->1.0 in //    over time anywhere from 12/sec or 60/sec. 

If all your properties are driven by the same parameter the animation will be smooth. As an added bonus, here is a tip for timing. As long as you can keep your t parameter between 0 and 1, easing in or out can be hacked with one line of code:

// After your t is all setup t = t * t;        // for easing in // or t = Math.sqrt(t); // for easing out 
Read More

Wednesday, March 9, 2016

Taking image from custom camera is stretched when save in ImageView

Leave a Comment

I am using this code to save pic in Imageview but the image is stretched when dsave in imageview. Camera preview is prefect and click right image but when i set that image in imageview the image is stetched.

    public void onPicTaken(byte[] data) {      if (data != null) {         int screenWidth = getResources().getDisplayMetrics().widthPixels;         int screenHeight = getResources().getDisplayMetrics().heightPixels;         Bitmap bm = BitmapFactory.decodeByteArray(data, 0, (data != null) ? data.length : 0);          if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {             // Notice that width and height are reversed             Bitmap scaled = Bitmap.createScaledBitmap(bm, screenHeight, screenWidth, true);             int w = scaled.getWidth();             int h = scaled.getHeight();             // Setting post rotate to 90             Matrix mtx = new Matrix();             mtx.postRotate(90);             // Rotating Bitmap             bm = Bitmap.createBitmap(scaled, 0, 0, w, h, mtx, true);         }else{// LANDSCAPE MODE             //No need to reverse width and height             Bitmap scaled = Bitmap.createScaledBitmap(bm, screenWidth,screenHeight , true);             bm=scaled;         }         ivCaptureImagePreview.setImageBitmap(bm);         ivCaptureImagePreview.setVisibility(View.VISIBLE);     }  } 

7 Answers

Answers 1

Use following class for creating scaled bitmap

public class ScalingUtilities  {      /**      * Utility function for decoding an image resource. The decoded bitmap will      * be optimized for further scaling to the requested destination dimensions      * and scaling logic.      *      * @param res The resources object containing the image data      * @param resId The resource id of the image data      * @param dstWidth Width of destination area      * @param dstHeight Height of destination area      * @param scalingLogic Logic to use to avoid image stretching      * @return Decoded bitmap      */     public static Bitmap decodeResource(Resources res, int resId, int dstWidth, int dstHeight,             ScalingLogic scalingLogic) {         Options options = new Options();         options.inJustDecodeBounds = true;         BitmapFactory.decodeResource(res, resId, options);         options.inJustDecodeBounds = false;         options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, dstWidth,                 dstHeight, scalingLogic);         Bitmap unscaledBitmap = BitmapFactory.decodeResource(res, resId, options);          return unscaledBitmap;     }      /**      * Utility function for creating a scaled version of an existing bitmap      *      * @param unscaledBitmap Bitmap to scale      * @param dstWidth Wanted width of destination bitmap      * @param dstHeight Wanted height of destination bitmap      * @param scalingLogic Logic to use to avoid image stretching      * @return New scaled bitmap object      */     public static Bitmap createScaledBitmap(Bitmap unscaledBitmap, int dstWidth, int dstHeight,             ScalingLogic scalingLogic) {         Rect srcRect = calculateSrcRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight(),                 dstWidth, dstHeight, scalingLogic);         Rect dstRect = calculateDstRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight(),                 dstWidth, dstHeight, scalingLogic);         Bitmap scaledBitmap = Bitmap.createBitmap(dstRect.width(), dstRect.height(),                 Config.ARGB_8888);         Canvas canvas = new Canvas(scaledBitmap);         canvas.drawBitmap(unscaledBitmap, srcRect, dstRect, new Paint(Paint.FILTER_BITMAP_FLAG));          return scaledBitmap;     }      /**      * ScalingLogic defines how scaling should be carried out if source and      * destination image has different aspect ratio.      *      * CROP: Scales the image the minimum amount while making sure that at least      * one of the two dimensions fit inside the requested destination area.      * Parts of the source image will be cropped to realize this.      *      * FIT: Scales the image the minimum amount while making sure both      * dimensions fit inside the requested destination area. The resulting      * destination dimensions might be adjusted to a smaller size than      * requested.      */     public static enum ScalingLogic {         CROP, FIT     }      /**      * Calculate optimal down-sampling factor given the dimensions of a source      * image, the dimensions of a destination area and a scaling logic.      *      * @param srcWidth Width of source image      * @param srcHeight Height of source image      * @param dstWidth Width of destination area      * @param dstHeight Height of destination area      * @param scalingLogic Logic to use to avoid image stretching      * @return Optimal down scaling sample size for decoding      */     public static int calculateSampleSize(int srcWidth, int srcHeight, int dstWidth, int dstHeight,             ScalingLogic scalingLogic) {         if (scalingLogic == ScalingLogic.FIT) {             final float srcAspect = (float)srcWidth / (float)srcHeight;             final float dstAspect = (float)dstWidth / (float)dstHeight;              if (srcAspect > dstAspect) {                 return srcWidth / dstWidth;             } else {                 return srcHeight / dstHeight;             }         } else {             final float srcAspect = (float)srcWidth / (float)srcHeight;             final float dstAspect = (float)dstWidth / (float)dstHeight;              if (srcAspect > dstAspect) {                 return srcHeight / dstHeight;             } else {                 return srcWidth / dstWidth;             }         }     }      /**      * Calculates source rectangle for scaling bitmap      *      * @param srcWidth Width of source image      * @param srcHeight Height of source image      * @param dstWidth Width of destination area      * @param dstHeight Height of destination area      * @param scalingLogic Logic to use to avoid image stretching      * @return Optimal source rectangle      */     public static Rect calculateSrcRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight,             ScalingLogic scalingLogic) {         if (scalingLogic == ScalingLogic.CROP) {             final float srcAspect = (float)srcWidth / (float)srcHeight;             final float dstAspect = (float)dstWidth / (float)dstHeight;              if (srcAspect > dstAspect) {                 final int srcRectWidth = (int)(srcHeight * dstAspect);                 final int srcRectLeft = (srcWidth - srcRectWidth) / 2;                 return new Rect(srcRectLeft, 0, srcRectLeft + srcRectWidth, srcHeight);             } else {                 final int srcRectHeight = (int)(srcWidth / dstAspect);                 final int scrRectTop = (int)(srcHeight - srcRectHeight) / 2;                 return new Rect(0, scrRectTop, srcWidth, scrRectTop + srcRectHeight);             }         } else {             return new Rect(0, 0, srcWidth, srcHeight);         }     }      /**      * Calculates destination rectangle for scaling bitmap      *      * @param srcWidth Width of source image      * @param srcHeight Height of source image      * @param dstWidth Width of destination area      * @param dstHeight Height of destination area      * @param scalingLogic Logic to use to avoid image stretching      * @return Optimal destination rectangle      */     public static Rect calculateDstRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight,             ScalingLogic scalingLogic) {         if (scalingLogic == ScalingLogic.FIT) {             final float srcAspect = (float)srcWidth / (float)srcHeight;             final float dstAspect = (float)dstWidth / (float)dstHeight;              if (srcAspect > dstAspect) {                 return new Rect(0, 0, dstWidth, (int)(dstWidth / srcAspect));             } else {                 return new Rect(0, 0, (int)(dstHeight * srcAspect), dstHeight);             }         } else {             return new Rect(0, 0, dstWidth, dstHeight);         }     }   } 

and use this class in your function as below

public void onPicTaken(byte[] data) {      if (data != null) {         int screenWidth = getResources().getDisplayMetrics().widthPixels;         int screenHeight = getResources().getDisplayMetrics().heightPixels;         Bitmap bm = BitmapFactory.decodeByteArray(data, 0, (data != null) ? data.length : 0);          if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {             // Notice that width and height are reversed             Bitmap scaled = ScalingUtilities.createScaledBitmap(bm, screenHeight, screenWidth, ScalingLogic.FIT);             int w = scaled.getWidth();             int h = scaled.getHeight();             // Setting post rotate to 90             Matrix mtx = new Matrix();             mtx.postRotate(90);             // Rotating Bitmap             bm = Bitmap.createBitmap(scaled, 0, 0, w, h, mtx, true);         }else{// LANDSCAPE MODE             //No need to reverse width and height             Bitmap scaled = ScalingUtilities.createScaledBitmap(bm, screenHeight, screenWidth, ScalingLogic.FIT);             bm=scaled;         }         ivCaptureImagePreview.setImageBitmap(bm);         ivCaptureImagePreview.setVisibility(View.VISIBLE);     }  } 

Answers 2

UIImageView Settings

<ImageView     android:id="@id/img"     android:layout_width="match_parent"     android:layout_height="wrap_content"     android:adjustViewBounds="true"     android:scaleType="fitCenter" /> 

My Test Application for this Problem

For Getting the Picture From the Camera, I use the following methods:

private void pickImageIntent() {     Intent pickPhoto = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);     getCurrentActivity().startActivityForResult(pickPhoto, REQUEST_PICK_IMAGE); }  private void takeImageIntent() {     try     {         File outputDir = getCurrentActivity().getExternalCacheDir();         File outputFile = File.createTempFile("prefix", "extension", outputDir);         selectedImageUri = Uri.fromFile(outputFile);          Intent takePicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);         takePicture.putExtra(MediaStore.EXTRA_OUTPUT, selectedImageUri);         getCurrentActivity().startActivityForResult(takePicture, REQUEST_TAKE_IMAGE);     }     catch (IOException e)     {         e.printStackTrace();     } } 

For Getting the Result From the Camera or Image Picker, and show it in the imageView. Here this.myInterfaceImage:

public void onActivityResult(int requestCode, int resultCode, Intent data) {     switch(requestCode)     {         case REQUEST_PICK_IMAGE:             if(resultCode == Activity.RESULT_OK)             {                 selectedImageUri = data.getData();                 initImage(selectedImageUri);             }             break;         case REQUEST_TAKE_IMAGE:             if(resultCode == Activity.RESULT_OK)             {                 initImage(selectedImageUri);             }             break;     } }   protected void initImage(Uri selectedImageUri_) {     try {         ParcelFileDescriptor parcelFileDescriptor = getContext().getContentResolver().openFileDescriptor(selectedImageUri_, "r");         FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();         Bitmap source = BitmapFactory.decodeFileDescriptor(fileDescriptor);         float ratio = (float)source.getWidth() /  (float)source.getHeight();         // here perhaps limit the size of the image         int height =   Math.min(getContext().getResources().getDisplayMetrics().heightPixels, source.getHeight());         int width = (int)(ratio*height);         Bitmap result = Bitmap.createScaledBitmap(source, width, height, false);         this.interfaceImage.setImageBitmap(result);         if (result != source) {             source.recycle();         }     } catch (Exception ex) {         System.out.println("File not found");     } } 

This is how I used this in My Test Application, and it works I don't have any orientation issues. I tested in Portrait mode with Portrait and Landscape Picture, and in Landscape mode with Portrait and Landscape Picture. And with both where I changed the orientation after before getting the Image.

If your are using Custom Camera and the orientation is wrong with the Code Above, just add this

There are two things needed:

  1. Camera preview need the same as your rotation. Set this by

    camera.setDisplayOrientation(result);

  2. Save the picture captured as your camera preview. Do this via Camera.Parameters.

    int mRotation = getCameraDisplayOrientation(); Camera.Parameters parameters = camera.getParameters(); parameters.setRotation(mRotation); //set rotation to save the picture camera.setDisplayOrientation(result); //set the rotation for preview camera camera.setParameters(parameters);

Then you can use your function without the orientation stuff

public void onPicTaken(byte[] data) {     if (data != null) {         Bitmap bm = BitmapFactory.decodeByteArray(data, 0, (data != null) ? data.length : 0);         int screenWidth = getResources().getDisplayMetrics().widthPixels;         float ratio = (float)bm.getWidth() /  (float)bm.getHeight();         int screenHeight = (int)(ratio*screenWidth)         Bitmap scaled = Bitmap.createScaledBitmap(bm, screenHeight, screenWidth, true);         if (scaled != bm) {             source.recycle();         }                 ivCaptureImagePreview.setImageBitmap(scaled);         ivCaptureImagePreview.setVisibility(View.VISIBLE);     } } 

Hope that helps.

Answers 3

Use this it will prevent image from stretching and maintaining the aspect ratio of image

android:scaleType="fitXY"  // or desired scale type android:adjustViewBounds="true" 

Answers 4

I use this function in my one of project please check if it is useful for you.

public static Bitmap Preview(String path) {     //SCALE IMAGE     int SCALE = 4;     try {         BitmapFactory.Options o2 = new BitmapFactory.Options();         o2.inSampleSize = SCALE;         Bitmap bitmap = BitmapFactory.decodeFile(path, o2);         OutputStream os = new FileOutputStream(path);         bitmap.compress(Bitmap.CompressFormat.PNG, 100, os);         os.flush();         os.close();         File file = new File(path);          while (file.length() > 800000) {             SCALE += 2;             o2.inSampleSize = SCALE;             bitmap = BitmapFactory.decodeFile(path, o2);             os = new FileOutputStream(path);             bitmap.compress(Bitmap.CompressFormat.PNG, 100, os);             os.flush();             os.close();             file = new File(path);         }          bitmap = BitmapFactory.decodeFile(path, o2);         return bitmap;     } catch (Exception e) {         e.printStackTrace();         return null;     } } 

Answers 5

You can set scaleType in xml

<ImageView         android:id="@+id/iv_imageview"         android:layout_width="match_parent"         android:layout_height="match_parent"         android:scaleType="fitCenter" /> 

In Java code you can achieve same like this

ImageView mImageView = (ImageView) findViewById(R.id.iv_imageview);  mImageView.setScaleType(ImageView.ScaleType.FIT_CENTER);  

Answers 6

Scaling your bitmap with Bitmap.createScaledBitmap(bm, screenHeight, screenWidth, true); won't maintain aspect ratio because this will stretch the width and height of the bitmap to match the target.

An option would be to calculate the target height manually so no cropping occurs:

double aspectRatio = (double) source.getHeight() / (double) source.getWidth(); int targetHeight = (int) (screenWidth * aspectRatio); 

And then use targetHeight instead of screenHeight as height argument in createScaledBitmap().

In addition, make sure the imageview you load your bitmap into has the appropriate scale type (e.g. FIT_CENTER or CENTER_CROP).

Answers 7

use this putExtra in your intent call for camera

intent.putExtra("outputX", 80);     intent.putExtra("outputY", 80);     intent.putExtra("aspectX", 1);     intent.putExtra("aspectY", 1);     intent.putExtra("scale", true);     intent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, 20);      intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);     startActivityForResult(intent, Utility.REQUEST_FOR_CAMERA); 
Read More