├── .gitignore ├── AndroidManifest.xml ├── LICENSE ├── README.md ├── ic_launcher-web.png ├── libs └── android-support-v4.jar ├── lint.xml ├── proguard-project.txt ├── project.properties ├── res ├── drawable-hdpi │ └── ic_launcher.png ├── drawable-mdpi │ └── ic_launcher.png ├── drawable-xhdpi │ └── ic_launcher.png ├── drawable-xxhdpi │ └── ic_launcher.png ├── drawable │ ├── circle_dragger.xml │ └── josh_hood.jpg ├── layout │ ├── activity_display.xml │ └── activity_main.xml ├── menu │ └── main.xml ├── values-sw600dp │ └── dimens.xml ├── values-sw720dp-land │ └── dimens.xml ├── values-v11 │ └── styles.xml ├── values-v14 │ └── styles.xml └── values │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── screenshots └── screenshot_1.png └── src └── com └── joshholtz └── cropimageview ├── CropImageView.java └── test ├── DisplayActivity.java └── MainActivity.java /.gitignore: -------------------------------------------------------------------------------- 1 | # built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # files for the dex VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # generated files 12 | bin/ 13 | gen/ 14 | 15 | # Local configuration file (sdk path, etc) 16 | local.properties 17 | 18 | .project 19 | .classpath 20 | -------------------------------------------------------------------------------- /AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 16 | 17 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Josh Holtz 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CropImageView - Android 2 | 3 | Super easy component for Android to crop an image 4 | 5 | ![](https://raw.github.com/joshdholtz/CropImageView/master/screenshots/screenshot_1.png) 6 | 7 | ### Installation 8 | 9 | - Download JAR from releases [crop-image-view-0.0.1.jar](https://github.com/joshdholtz/CropImageView/releases/tag/crop-image-view-0.0.1) 10 | - Download and use as an Android library project 11 | 12 | ### Example 13 | 14 | ````xml 15 | 16 | 23 | 24 | ```` 25 | 26 | ````java 27 | 28 | public class MainActivity extends Activity { 29 | 30 | CropImageView cropImageView; 31 | 32 | @Override 33 | protected void onCreate(Bundle savedInstanceState) { 34 | super.onCreate(savedInstanceState); 35 | setContentView(R.layout.activity_main); 36 | 37 | cropImageView = (CropImageView) this.findViewById(R.id.crop_image_view); 38 | cropImageView.setImageResource(getResources(), R.drawable.josh_hood); 39 | 40 | // OPTIONAL - set corner color size and crop area color 41 | // cropImageView.setCornerDrawable(Color.rgb(255, 200, 0), 100, 100); 42 | // cropImageView.setCropAreaDrawable(Color.LTGRAY, 150, Color.CYAN, 200, 8); 43 | 44 | // OPTIONAL - keep crop square 45 | // cropImageView.setKeepSquare(true); 46 | } 47 | 48 | @Override 49 | public boolean onCreateOptionsMenu(Menu menu) { 50 | getMenuInflater().inflate(R.menu.main, menu); 51 | 52 | return(super.onCreateOptionsMenu(menu)); 53 | } 54 | 55 | @Override 56 | public boolean onOptionsItemSelected(MenuItem item) { 57 | if (item.getItemId() == R.id.action_crop) { 58 | try { 59 | DisplayActivity.imageToShow = cropImageView.crop(this); 60 | 61 | Intent intent = new Intent(this, DisplayActivity.class); 62 | this.startActivity(intent); 63 | } catch (IllegalArgumentException e) { 64 | // Crop section is out of bounds of image 65 | } 66 | } 67 | 68 | return(super.onOptionsItemSelected(item)); 69 | } 70 | 71 | } 72 | 73 | ```` 74 | 75 | ## Author 76 | 77 | Josh Holtz, me@joshholtz.com, [@joshdholtz](https://twitter.com/joshdholtz) 78 | 79 | ## License 80 | 81 | CropImageView is available under the MIT license. See the LICENSE file for more info. 82 | -------------------------------------------------------------------------------- /ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshdholtz/CropImageView/9905d52918d94012e2b62a5c1ab5a0c129e15740/ic_launcher-web.png -------------------------------------------------------------------------------- /libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshdholtz/CropImageView/9905d52918d94012e2b62a5c1ab5a0c129e15740/libs/android-support-v4.jar -------------------------------------------------------------------------------- /lint.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-19 15 | android.library=true 16 | -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshdholtz/CropImageView/9905d52918d94012e2b62a5c1ab5a0c129e15740/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshdholtz/CropImageView/9905d52918d94012e2b62a5c1ab5a0c129e15740/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshdholtz/CropImageView/9905d52918d94012e2b62a5c1ab5a0c129e15740/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshdholtz/CropImageView/9905d52918d94012e2b62a5c1ab5a0c129e15740/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable/circle_dragger.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 9 | 12 | -------------------------------------------------------------------------------- /res/drawable/josh_hood.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshdholtz/CropImageView/9905d52918d94012e2b62a5c1ab5a0c129e15740/res/drawable/josh_hood.jpg -------------------------------------------------------------------------------- /res/layout/activity_display.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /res/menu/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /res/values-sw600dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /res/values-sw720dp-land/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 128dp 8 | 9 | 10 | -------------------------------------------------------------------------------- /res/values-v11/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /res/values-v14/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16dp 5 | 16dp 6 | 7 | 8 | -------------------------------------------------------------------------------- /res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CropImageView 5 | Crop 6 | Hello world! 7 | 8 | 9 | -------------------------------------------------------------------------------- /res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 14 | 15 | 16 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /screenshots/screenshot_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshdholtz/CropImageView/9905d52918d94012e2b62a5c1ab5a0c129e15740/screenshots/screenshot_1.png -------------------------------------------------------------------------------- /src/com/joshholtz/cropimageview/CropImageView.java: -------------------------------------------------------------------------------- 1 | package com.joshholtz.cropimageview; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.graphics.Bitmap; 6 | import android.graphics.BitmapFactory; 7 | import android.graphics.Color; 8 | import android.graphics.Paint.Style; 9 | import android.graphics.Rect; 10 | import android.graphics.drawable.Drawable; 11 | import android.graphics.drawable.LayerDrawable; 12 | import android.graphics.drawable.ShapeDrawable; 13 | import android.graphics.drawable.shapes.OvalShape; 14 | import android.graphics.drawable.shapes.RectShape; 15 | import android.util.AttributeSet; 16 | import android.util.Log; 17 | import android.view.MotionEvent; 18 | import android.view.View; 19 | import android.widget.FrameLayout; 20 | import android.widget.ImageView; 21 | import android.widget.ImageView.ScaleType; 22 | 23 | public class CropImageView extends FrameLayout implements View.OnTouchListener { 24 | 25 | private final static String TAG = "CropImageView"; 26 | 27 | private final static int HEIGHT_OF_DRAGGER = 45; 28 | private final static int INITIAL_MARGIN_OF_DRAGGER = 60; 29 | 30 | private ImageView mImageView; 31 | private ImageView mTopLeftDragger; 32 | private ImageView mBottomRightDragger; 33 | private ImageView mDaBox; 34 | 35 | private Drawable mDraggerDrawable; 36 | private Drawable mCropDrawable; 37 | 38 | private boolean mKeepSquare; 39 | 40 | private Bitmap mBitmap; 41 | 42 | public CropImageView(Context context) { 43 | super(context); 44 | init(); 45 | } 46 | 47 | public CropImageView(Context context, AttributeSet attrs) { 48 | super(context, attrs); 49 | init(); 50 | } 51 | 52 | public CropImageView(Context context, AttributeSet attrs, int defStyle) { 53 | super(context, attrs, defStyle); 54 | init(); 55 | } 56 | 57 | public void setImageBitmap(Bitmap bm) { 58 | if (mImageView != null) { 59 | mBitmap = bm; 60 | mImageView.setImageBitmap(bm); 61 | } 62 | } 63 | 64 | public void setCornerDrawable(int color, int width, int height) { 65 | mDraggerDrawable = this.getCircleDrawable(color, width, height); 66 | 67 | if (mTopLeftDragger != null) { 68 | mTopLeftDragger.setImageDrawable(mDraggerDrawable); 69 | } 70 | 71 | if (mBottomRightDragger != null) { 72 | mBottomRightDragger.setImageDrawable(mDraggerDrawable); 73 | } 74 | } 75 | 76 | public void setKeepSquare(boolean keepSquare) { 77 | mKeepSquare = keepSquare; 78 | 79 | if (mTopLeftDragger != null && mBottomRightDragger != null) { 80 | Log.d(TAG, "Draggers exist"); 81 | } else { 82 | Log.d(TAG, "Draggers don't exist"); 83 | } 84 | } 85 | 86 | public void setCropAreaDrawable(int fillColor, int fillAlpha, int strokeColor, int strokeAlpha, int strokeWidth) { 87 | mCropDrawable = this.getCropDrawable(fillColor, fillAlpha, strokeColor, strokeAlpha, strokeWidth); 88 | 89 | if (mDaBox != null) { 90 | if (android.os.Build.VERSION.SDK_INT < 16) { 91 | mDaBox.setBackgroundDrawable(mCropDrawable); 92 | } else { 93 | mDaBox.setBackground(mCropDrawable); 94 | } 95 | } 96 | } 97 | 98 | public void setImageResource(Resources resources, int resId) { 99 | this.setImageBitmap(BitmapFactory.decodeResource(getResources(), resId)); 100 | } 101 | 102 | public Bitmap crop(Context context) throws IllegalArgumentException { 103 | // Weird padding cause image size 104 | int weirdSidePadding = this.getWeirdSideMargin(); 105 | int weirdVerticalPadding = this.getWeirdVerticalMargin(); 106 | 107 | FrameLayout.LayoutParams params = (LayoutParams) mDaBox.getLayoutParams(); 108 | 109 | // Getting crop dimensions 110 | float d = context.getResources().getDisplayMetrics().density; 111 | int x = (int)((params.leftMargin - weirdSidePadding) * d); 112 | int y = (int)((params.topMargin - weirdVerticalPadding) * d); 113 | int width = (int)((this.getWidth() - params.leftMargin - params.rightMargin) * d); 114 | int height = (int)((this.getHeight() - params.topMargin - params.bottomMargin) * d); 115 | 116 | Bitmap crooopppppppppppppppeed = Bitmap.createBitmap(mBitmap, x, y, width, height); 117 | 118 | return crooopppppppppppppppeed; 119 | } 120 | 121 | private void init() { 122 | mDraggerDrawable = this.getCircleDrawable(Color.rgb(255, 200, 0), HEIGHT_OF_DRAGGER, HEIGHT_OF_DRAGGER); 123 | mCropDrawable = this.getCropDrawable(Color.LTGRAY, 150, Color.LTGRAY, 255, 8); 124 | 125 | if (mImageView == null) { 126 | mImageView = new ImageView(this.getContext()); 127 | 128 | FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); 129 | this.addView(mImageView, params); 130 | } 131 | 132 | } 133 | 134 | @Override 135 | protected void onLayout( boolean changed, int left, int top, int right, int bottom ) { 136 | super.onLayout(changed, left, top, right, bottom); 137 | 138 | if (mTopLeftDragger == null) { 139 | mTopLeftDragger = new ImageView(this.getContext()); 140 | mTopLeftDragger.setImageDrawable(mDraggerDrawable); 141 | mTopLeftDragger.setOnTouchListener(this); 142 | 143 | FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); 144 | params.setMargins(INITIAL_MARGIN_OF_DRAGGER, INITIAL_MARGIN_OF_DRAGGER, 0, 0); 145 | this.addView(mTopLeftDragger, params); 146 | } 147 | 148 | if (mBottomRightDragger == null) { 149 | mBottomRightDragger = new ImageView(this.getContext()); 150 | mBottomRightDragger.setImageDrawable(mDraggerDrawable); 151 | mBottomRightDragger.setOnTouchListener(this); 152 | 153 | int width = this.getWidth(); 154 | int height = this.getHeight(); 155 | 156 | int leftMargin = width - INITIAL_MARGIN_OF_DRAGGER - HEIGHT_OF_DRAGGER; 157 | int topMargin = height - INITIAL_MARGIN_OF_DRAGGER - HEIGHT_OF_DRAGGER; 158 | int rightMargin = 0; 159 | int bottomMargin = 0; 160 | 161 | if (mKeepSquare) { 162 | int smallestMargin = Math.min(leftMargin, topMargin); 163 | leftMargin = smallestMargin; 164 | topMargin = smallestMargin; 165 | } 166 | 167 | FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); 168 | params.setMargins(leftMargin, topMargin, rightMargin, bottomMargin); 169 | this.addView(mBottomRightDragger, params); 170 | } 171 | 172 | if (mDaBox == null) { 173 | mDaBox = new ImageView(this.getContext()); 174 | // mDaBox.setImageDrawable(this.getCropDrawable()); 175 | if (android.os.Build.VERSION.SDK_INT < 16) { 176 | mDaBox.setBackgroundDrawable(mCropDrawable); 177 | } else { 178 | mDaBox.setBackground(mCropDrawable); 179 | } 180 | mDaBox.setScaleType(ScaleType.MATRIX); 181 | mDaBox.setAdjustViewBounds(true); 182 | mDaBox.setOnTouchListener(this); 183 | // mDaBox.setBackgroundColor(Color.WHITE); 184 | 185 | // FrameLayout.LayoutParams paramsTopLeft = (LayoutParams) mTopLeftDragger.getLayoutParams(); 186 | // FrameLayout.LayoutParams paramsBottomRight = (LayoutParams) mBottomRightDragger.getLayoutParams(); 187 | // 188 | // int leftMargin = (int) (paramsTopLeft.leftMargin + (HEIGHT_OF_DRAGGER/2.0)); 189 | // int topMargin = (int) (paramsTopLeft.topMargin + (HEIGHT_OF_DRAGGER/2.0)); 190 | // int rightMargin = (int) (paramsBottomRight.rightMargin + HEIGHT_OF_DRAGGER + INITIAL_MARGIN_OF_DRAGGER); 191 | // int bottomMargin = (int) (paramsBottomRight.bottomMargin + HEIGHT_OF_DRAGGER + INITIAL_MARGIN_OF_DRAGGER); 192 | // 193 | FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); 194 | // params.setMargins(leftMargin, topMargin, rightMargin, bottomMargin); 195 | this.addView(mDaBox, 1, params); 196 | 197 | moveCrop(); 198 | } 199 | } 200 | 201 | FrameLayout.LayoutParams parms; 202 | // LinearLayout.LayoutParams par; 203 | float dx=0,dy=0,x=0,y=0; 204 | 205 | @Override 206 | public boolean onTouch(View v, MotionEvent event) { 207 | switch(event.getAction()) 208 | { 209 | case MotionEvent.ACTION_DOWN : 210 | { 211 | // if (v == mTopLeftDragger || v == mBottomRightDragger) { 212 | parms = (LayoutParams) v.getLayoutParams(); 213 | dx = event.getRawX() - parms.leftMargin; 214 | dy = event.getRawY() - parms.topMargin; 215 | // } else if (v == mDaBox) { 216 | // 217 | // } 218 | } 219 | break; 220 | case MotionEvent.ACTION_MOVE : 221 | { 222 | x = event.getRawX(); 223 | y = event.getRawY(); 224 | 225 | if (v == mTopLeftDragger || v == mBottomRightDragger) { 226 | int leftMargin = (int) (x-dx); 227 | int topMargin = (int) (y - dy); 228 | 229 | if (mKeepSquare) { 230 | int dLeft = leftMargin - parms.leftMargin; 231 | int dTop = topMargin - parms.topMargin; 232 | 233 | int smallestMargin = Math.min(dLeft, dTop); 234 | leftMargin = smallestMargin; 235 | topMargin = smallestMargin; 236 | 237 | parms.leftMargin += smallestMargin; 238 | parms.topMargin += smallestMargin; 239 | } else { 240 | parms.leftMargin = leftMargin; 241 | parms.topMargin = topMargin; 242 | } 243 | 244 | 245 | v.setLayoutParams(parms); 246 | 247 | moveCrop(); 248 | } else if (v == mDaBox) { 249 | int leftMargin = (int) (x-dx); 250 | int topMargin = (int) (y - dy); 251 | 252 | int dLeft = leftMargin - parms.leftMargin; 253 | int dTop = topMargin - parms.topMargin; 254 | 255 | parms.leftMargin = leftMargin; 256 | parms.topMargin = topMargin; 257 | parms.rightMargin -= dLeft; 258 | parms.bottomMargin -= dTop; 259 | v.setLayoutParams(parms); 260 | 261 | FrameLayout.LayoutParams topLeftParams = (LayoutParams) mTopLeftDragger.getLayoutParams(); 262 | topLeftParams.leftMargin += dLeft; 263 | topLeftParams.topMargin += dTop; 264 | mTopLeftDragger.setLayoutParams(topLeftParams); 265 | 266 | FrameLayout.LayoutParams bottomRightParams = (LayoutParams) mBottomRightDragger.getLayoutParams(); 267 | bottomRightParams.leftMargin += dLeft; 268 | bottomRightParams.topMargin += dTop; 269 | mBottomRightDragger.setLayoutParams(bottomRightParams); 270 | } 271 | } 272 | break; 273 | case MotionEvent.ACTION_UP : 274 | { 275 | 276 | } 277 | break; 278 | } 279 | return true; 280 | } 281 | 282 | private void moveCrop() { 283 | FrameLayout.LayoutParams paramsTopLeft = (LayoutParams) mTopLeftDragger.getLayoutParams(); 284 | FrameLayout.LayoutParams paramsBottomRight = (LayoutParams) mBottomRightDragger.getLayoutParams(); 285 | 286 | int width = this.getWidth(); 287 | int height = this.getHeight(); 288 | 289 | int widthOfCorner = mDraggerDrawable.getIntrinsicWidth(); 290 | int heightOfCorner = mDraggerDrawable.getIntrinsicHeight(); 291 | 292 | int leftMargin = (int) (paramsTopLeft.leftMargin + (widthOfCorner/2.0f)); 293 | int topMargin = (int) (paramsTopLeft.topMargin + (heightOfCorner/2.0f)); 294 | int rightMargin = (int) (width - paramsBottomRight.leftMargin - (widthOfCorner/2.0f)); 295 | int bottomMargin = (int) (height - paramsBottomRight.topMargin - (heightOfCorner/2.0f)); 296 | 297 | FrameLayout.LayoutParams params = (LayoutParams) mDaBox.getLayoutParams();; 298 | params.leftMargin = leftMargin; 299 | params.topMargin = topMargin; 300 | params.rightMargin = rightMargin; 301 | params.bottomMargin = bottomMargin; 302 | mDaBox.setLayoutParams(params); 303 | 304 | } 305 | 306 | private Drawable getCircleDrawable(int color, int width, int height) { 307 | ShapeDrawable biggerCircle= new ShapeDrawable( new OvalShape()); 308 | biggerCircle.setIntrinsicWidth( width); 309 | biggerCircle.setIntrinsicHeight( height ); 310 | biggerCircle.setBounds(new Rect(0, 0, width, height)); 311 | biggerCircle.getPaint().setColor(color); 312 | 313 | return biggerCircle; 314 | } 315 | 316 | private Drawable getCropDrawable(int fillColor, int fillAlpha, int strokeColor, int strokeAlpha, int strokeWidth) { 317 | ShapeDrawable sd1 = new ShapeDrawable(new RectShape()); 318 | sd1.getPaint().setColor(strokeColor); 319 | sd1.getPaint().setStyle(Style.STROKE); 320 | sd1.getPaint().setStrokeWidth(strokeWidth); 321 | sd1.setAlpha(255); 322 | 323 | ShapeDrawable sd2 = new ShapeDrawable(new RectShape()); 324 | sd2.getPaint().setColor(fillColor); 325 | sd2.getPaint().setStyle(Style.FILL); 326 | sd2.setAlpha(fillAlpha); 327 | 328 | Drawable[] layers = new Drawable[2]; 329 | layers[0] = sd1; 330 | layers[1] = sd2; 331 | LayerDrawable composite = new LayerDrawable(layers); 332 | 333 | return composite; 334 | } 335 | 336 | private int getWeirdSideMargin() { 337 | // Weird padding cause image size 338 | int weirdSidePadding = 0; 339 | 340 | // Image width / height ration 341 | double bitmapRatio = ((double)mBitmap.getWidth() / (double)mBitmap.getHeight()); 342 | 343 | // Image width / height ration 344 | double thisRatio = ((double)this.getWidth() / (double)this.getHeight()); 345 | 346 | // Magic math 347 | if (bitmapRatio < thisRatio) { 348 | int bitmapWidth = (int) (bitmapRatio * this.getHeight()); 349 | weirdSidePadding = (int) ((this.getWidth() - bitmapWidth) / 2.0); 350 | } else { 351 | 352 | } 353 | 354 | return weirdSidePadding; 355 | } 356 | 357 | private int getWeirdVerticalMargin() { 358 | // Weird padding cause image size 359 | int weirdVerticalPadding = 0; 360 | 361 | // Image width / height ration 362 | double bitmapRatio = ((double)mBitmap.getWidth() / (double)mBitmap.getHeight()); 363 | 364 | // Image width / height ration 365 | double thisRatio = ((double)this.getWidth() / (double)this.getHeight()); 366 | 367 | // Magic math 368 | if (bitmapRatio < thisRatio) { 369 | 370 | } else { 371 | int bitmapHeight = (int) (bitmapRatio * this.getWidth()); 372 | weirdVerticalPadding = (int) ((this.getHeight() - bitmapHeight) / 2.0); 373 | } 374 | 375 | return weirdVerticalPadding; 376 | } 377 | 378 | } 379 | -------------------------------------------------------------------------------- /src/com/joshholtz/cropimageview/test/DisplayActivity.java: -------------------------------------------------------------------------------- 1 | package com.joshholtz.cropimageview.test; 2 | 3 | import com.joshholtz.cropimageview.R; 4 | 5 | import android.os.Bundle; 6 | import android.widget.ImageView; 7 | import android.app.Activity; 8 | import android.graphics.Bitmap; 9 | 10 | public class DisplayActivity extends Activity { 11 | 12 | public static Bitmap imageToShow; 13 | 14 | ImageView imageView; 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | setContentView(R.layout.activity_display); 20 | 21 | imageView = (ImageView) this.findViewById(R.id.image_view); 22 | imageView.setImageBitmap(imageToShow); 23 | 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/com/joshholtz/cropimageview/test/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.joshholtz.cropimageview.test; 2 | 3 | import com.joshholtz.cropimageview.CropImageView; 4 | import com.joshholtz.cropimageview.R; 5 | 6 | import android.os.Bundle; 7 | import android.view.Menu; 8 | import android.view.MenuItem; 9 | import android.app.Activity; 10 | import android.content.Intent; 11 | import android.graphics.Color; 12 | 13 | public class MainActivity extends Activity { 14 | 15 | CropImageView cropImageView; 16 | 17 | @Override 18 | protected void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.activity_main); 21 | 22 | cropImageView = (CropImageView) this.findViewById(R.id.crop_image_view); 23 | cropImageView.setImageResource(getResources(), R.drawable.josh_hood); 24 | 25 | // OPTIONAL - set corner color size and crop area color 26 | // cropImageView.setCornerDrawable(Color.rgb(255, 200, 0), 100, 100); 27 | // cropImageView.setCropAreaDrawable(Color.LTGRAY, 150, Color.CYAN, 200, 8); 28 | 29 | // OPTIONAL - keep crop square 30 | // cropImageView.setKeepSquare(true); 31 | } 32 | 33 | @Override 34 | public boolean onCreateOptionsMenu(Menu menu) { 35 | getMenuInflater().inflate(R.menu.main, menu); 36 | 37 | return(super.onCreateOptionsMenu(menu)); 38 | } 39 | 40 | @Override 41 | public boolean onOptionsItemSelected(MenuItem item) { 42 | if (item.getItemId() == R.id.action_crop) { 43 | try { 44 | DisplayActivity.imageToShow = cropImageView.crop(this); 45 | 46 | Intent intent = new Intent(this, DisplayActivity.class); 47 | this.startActivity(intent); 48 | } catch (IllegalArgumentException e) { 49 | // Crop section is out of bounds of image 50 | } 51 | } 52 | 53 | return(super.onOptionsItemSelected(item)); 54 | } 55 | 56 | } 57 | --------------------------------------------------------------------------------