100 |
102 |
103 | License
104 | -------
105 |
106 | Copyright 2013 Manuel Peinado
107 |
108 | Licensed under the Apache License, Version 2.0 (the "License");
109 | you may not use this file except in compliance with the License.
110 | You may obtain a copy of the License at
111 |
112 | http://www.apache.org/licenses/LICENSE-2.0
113 |
114 | Unless required by applicable law or agreed to in writing, software
115 | distributed under the License is distributed on an "AS IS" BASIS,
116 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
117 | See the License for the specific language governing permissions and
118 | limitations under the License.
119 |
120 | [1]: https://raw.github.com/ManuelPeinado/ImageLayout/master/art/readme_pic.png
121 | [2]: https://github.com/ManuelPeinado/ImageLayout/tree/master/sample
122 |
--------------------------------------------------------------------------------
/art/boroughs-framed-all.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelPeinado/ImageLayout/6be0b5dc361ca1e1039cd8c40ad63721b7a1a154/art/boroughs-framed-all.png
--------------------------------------------------------------------------------
/art/boroughs-framed-galaxy_mini.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelPeinado/ImageLayout/6be0b5dc361ca1e1039cd8c40ad63721b7a1a154/art/boroughs-framed-galaxy_mini.png
--------------------------------------------------------------------------------
/art/boroughs-framed-galaxy_nexus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelPeinado/ImageLayout/6be0b5dc361ca1e1039cd8c40ad63721b7a1a154/art/boroughs-framed-galaxy_nexus.png
--------------------------------------------------------------------------------
/art/boroughs-framed-nexus7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelPeinado/ImageLayout/6be0b5dc361ca1e1039cd8c40ad63721b7a1a154/art/boroughs-framed-nexus7.png
--------------------------------------------------------------------------------
/art/boroughs-framed-nexus_s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelPeinado/ImageLayout/6be0b5dc361ca1e1039cd8c40ad63721b7a1a154/art/boroughs-framed-nexus_s.png
--------------------------------------------------------------------------------
/art/boroughs-framed_xoom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelPeinado/ImageLayout/6be0b5dc361ca1e1039cd8c40ad63721b7a1a154/art/boroughs-framed_xoom.png
--------------------------------------------------------------------------------
/art/hi_res_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelPeinado/ImageLayout/6be0b5dc361ca1e1039cd8c40ad63721b7a1a154/art/hi_res_icon.png
--------------------------------------------------------------------------------
/art/readme_pic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelPeinado/ImageLayout/6be0b5dc361ca1e1039cd8c40ad63721b7a1a154/art/readme_pic.png
--------------------------------------------------------------------------------
/art/snapshot0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelPeinado/ImageLayout/6be0b5dc361ca1e1039cd8c40ad63721b7a1a154/art/snapshot0.png
--------------------------------------------------------------------------------
/art/snapshot1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelPeinado/ImageLayout/6be0b5dc361ca1e1039cd8c40ad63721b7a1a154/art/snapshot1.png
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | mavenCentral()
4 | }
5 |
6 | dependencies {
7 | classpath 'com.android.tools.build:gradle:0.9.+'
8 | }
9 | }
10 |
11 | def isReleaseBuild() {
12 | return version.contains("SNAPSHOT") == false
13 | }
14 |
15 | allprojects {
16 | version = VERSION_NAME
17 | group = GROUP
18 |
19 | repositories {
20 | mavenCentral()
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | VERSION_NAME=1.1.0
2 | VERSION_CODE=110
3 | GROUP=com.github.manuelpeinado.imagelayout
4 |
5 | POM_DESCRIPTION=https://github.com/ManuelPeinado/ImageLayout
6 | POM_URL=https://github.com/ManuelPeinado/ImageLayout
7 | POM_SCM_URL=https://github.com/ManuelPeinado/ImageLayout
8 | POM_SCM_CONNECTION=scm:git@github.com:ManuelPeinado/ImageLayout.git
9 | POM_SCM_DEV_CONNECTION=scm:git@github.com:ManuelPeinado/ImageLayout.git
10 | POM_LICENCE_NAME=The Apache Software License, Version 2.0
11 | POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
12 | POM_LICENCE_DIST=repo
13 | POM_DEVELOPER_ID=manuelpeinado
14 | POM_DEVELOPER_NAME=Manuel Peinado
15 |
16 | ANDROID_BUILD_TOOLS_VERSION=19
17 | ANDROID_COMPILE_SDK_VERSION=19
18 | ANDROID_TARGET_SDK_VERSION=19
19 | ANDROID_MIN_SDK=4
--------------------------------------------------------------------------------
/library/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/library/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'android-library'
2 |
3 |
4 | android {
5 | compileSdkVersion Integer.parseInt(project.ANDROID_COMPILE_SDK_VERSION)
6 | buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION
7 |
8 | defaultConfig {
9 | minSdkVersion Integer.parseInt(project.ANDROID_MIN_SDK)
10 | targetSdkVersion Integer.parseInt(project.ANDROID_TARGET_SDK_VERSION)
11 | }
12 |
13 | sourceSets {
14 | main {
15 | manifest.srcFile 'AndroidManifest.xml'
16 | java.srcDirs = ['src']
17 | res.srcDirs = ['res']
18 | }
19 | }
20 |
21 | lintOptions {
22 | abortOnError false
23 | }
24 | }
25 |
26 | apply from: '../maven_push.gradle'
27 |
28 |
29 |
--------------------------------------------------------------------------------
/library/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=ImageLayout
2 | POM_ARTIFACT_ID=imagelayout
3 | POM_PACKAGING=aar
4 |
--------------------------------------------------------------------------------
/library/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-18
15 | android.library=true
16 |
--------------------------------------------------------------------------------
/library/res/values/il__attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
24 |
25 |
31 |
32 |
38 |
39 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/library/src/com/manuelpeinado/imagelayout/ImageFitter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Manuel Peinado
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.manuelpeinado.imagelayout;
17 |
18 | import android.graphics.Bitmap;
19 | import android.graphics.Rect;
20 | import android.view.Gravity;
21 |
22 | class ImageFitter {
23 | private int gravity;
24 | private int fitMode;
25 |
26 | ImageFitter(int mode, int gravity) {
27 | this.fitMode = mode;
28 | this.gravity = gravity;
29 | }
30 |
31 | Rect fit(Bitmap bmp, int viewWidth, int viewHeight) {
32 | switch (fitMode) {
33 | case ImageLayout.FIT_VERTICAL:
34 | return fitVertical(bmp, viewWidth, viewHeight);
35 | case ImageLayout.FIT_HORIZONTAL:
36 | return fitHorizontal(bmp, viewWidth, viewHeight);
37 | case ImageLayout.FIT_BOTH:
38 | return fitBoth(bmp, viewWidth, viewHeight);
39 | default:
40 | return fitAuto(bmp, viewWidth, viewHeight);
41 | }
42 | }
43 |
44 | private Rect fitHorizontal(Bitmap bmp, int w, int h) {
45 | float bitmapAspectRatio = computeBitmapAspectRatio(bmp);
46 | return fitHorizontal(w, h, bitmapAspectRatio);
47 | }
48 |
49 | private Rect fitVertical(Bitmap bmp, int w, int h) {
50 | float bitmapAspectRatio = computeBitmapAspectRatio(bmp);
51 | return fitVertical(w, h, bitmapAspectRatio);
52 | }
53 |
54 | private Rect fitBoth(Bitmap bmp, int w, int h) {
55 | float bitmapAspectRatio = computeBitmapAspectRatio(bmp);
56 | float viewAspectRatio = w / (float) h;
57 | if (bitmapAspectRatio < viewAspectRatio) {
58 | return fitHorizontal(w, h, bitmapAspectRatio);
59 | }
60 | return fitVertical(w, h, bitmapAspectRatio);
61 | }
62 |
63 | private Rect fitAuto(Bitmap bmp, int w, int h) {
64 | float bitmapAspectRatio = computeBitmapAspectRatio(bmp);
65 | float viewAspectRatio = w / (float) h;
66 | if (bitmapAspectRatio > viewAspectRatio) {
67 | return fitHorizontal(w, h, bitmapAspectRatio);
68 | }
69 | return fitVertical(w, h, bitmapAspectRatio);
70 | }
71 |
72 | private Rect fitHorizontal(int w, int h, float bitmapAspectRatio) {
73 | int destWidth = w;
74 | int destHeight = (int) (destWidth / bitmapAspectRatio);
75 | int vGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
76 | int top = 0;
77 | if (vGravity == Gravity.CENTER_VERTICAL) {
78 | top = h / 2 - destHeight / 2;
79 | }
80 | else if (vGravity == Gravity.BOTTOM) {
81 | top = h - destHeight;
82 | }
83 | return new Rect(0, top, destWidth, top + destHeight);
84 | }
85 |
86 | private Rect fitVertical(int w, int h, float bitmapAspectRatio) {
87 | int destHeight = h;
88 | int destWidth = (int) (destHeight * bitmapAspectRatio);
89 | int hGravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
90 | int left = 0;
91 | if (hGravity == Gravity.CENTER_HORIZONTAL) {
92 | left = w / 2 - destWidth / 2;
93 | }
94 | else if (hGravity == Gravity.RIGHT) {
95 | left = w - destWidth;
96 | }
97 | return new Rect(left, 0, left + destWidth, destHeight);
98 | }
99 |
100 | private static float computeBitmapAspectRatio(Bitmap bmp) {
101 | return bmp.getWidth() / (float) bmp.getHeight();
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/library/src/com/manuelpeinado/imagelayout/ImageLayout.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Manuel Peinado
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.manuelpeinado.imagelayout;
17 |
18 | import android.content.Context;
19 | import android.content.res.TypedArray;
20 | import android.graphics.Bitmap;
21 | import android.graphics.Canvas;
22 | import android.graphics.Rect;
23 | import android.graphics.drawable.BitmapDrawable;
24 | import android.graphics.drawable.Drawable;
25 | import android.util.AttributeSet;
26 | import android.view.Gravity;
27 | import android.view.View;
28 | import android.view.ViewGroup;
29 |
30 | /**
31 | * A layout that arranges its children in relation to a background image. The
32 | * layout of each child is specified in image coordinates (pixels), and the
33 | * conversion to screen coordinates is performed automatically.
34 | * The background image is adjusted so that it fills the available space. The exact
35 | * details of this adjustment are controlled by the custom:fit and android:gravity
36 | * attributes
37 | *
For some applications this might be a useful replacement for the now
38 | * deprecated AbsoluteLayout.
39 | */
40 | public class ImageLayout extends ViewGroup {
41 |
42 | /**
43 | * The image is made to fill the available vertical space, and may be cropped
44 | * horizontally if there is not enough space.
45 | *
If there is too much horizontal space it is left blank.
46 | *
The vertical position of the image is controlled by the android:gravity attribute
47 | */
48 | public static final int FIT_VERTICAL = 0;
49 | /**
50 | * The image is made to fill the available horizontal space, and may be cropped
51 | * vertically if there is not enough space.
52 | *
If there is too much vertical space it is left blank.
53 | *
The vertical position of the image is controlled by the android:gravity attribute
54 | */
55 | public static final int FIT_HORIZONTAL = 1;
56 |
57 | /**
58 | * The image fills the available space both vertically and horizontally.
59 | *
If the aspect ratio of the image does not match exactly the aspect ratio
60 | * of the available space, the image is cropped either vertically or horizontally,
61 | * depending on which provides the best fit
62 | */
63 | public static final int FIT_BOTH = 2;
64 |
65 | /**
66 | * The image is made to fill the available space vertically in portrait mode
67 | * and horizontally in landscape.
68 | *
This is the default mode.
69 | *
Note that the library does not determine the orientation based on the
70 | * actual device orientation, but on the relative aspect ratios of the image
71 | * and the view.
72 | */
73 | public static final int FIT_AUTO = 3;
74 |
75 | /**
76 | * The fit mode that will be used in case the user does not specify one
77 | */
78 | public static final int DEFAULT_FIT_MODE = FIT_AUTO;
79 |
80 | private Bitmap bitmap;
81 | private Rect bitmapDestRect;
82 | private int imageWidth;
83 | private int imageHeight;
84 | private Rect bitmapSrcRect;
85 | private ImageFitter fitter;
86 | private int fitMode = DEFAULT_FIT_MODE;
87 | private int gravity = -1;
88 |
89 | public ImageLayout(Context context, AttributeSet attrs) {
90 | super(context, attrs);
91 | setWillNotDraw(false);
92 | parseAttributes(attrs);
93 | }
94 |
95 | private void parseAttributes(AttributeSet attrs) {
96 | if (attrs == null) {
97 | return;
98 | }
99 | TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ImageLayout);
100 | Drawable drawable = a.getDrawable(R.styleable.ImageLayout_image);
101 | if (drawable == null) {
102 | throw new RuntimeException("Invalid drawable resource in layout description file");
103 | }
104 | if (!(drawable instanceof BitmapDrawable)) {
105 | throw new RuntimeException("Drawable resource in layout description file must be of type \"BitmapDrawable\"");
106 | }
107 |
108 | bitmap = extractBitmapFromDrawable(drawable);
109 | bitmapSrcRect = bitmapRect(bitmap);
110 |
111 | imageWidth = a.getInteger(R.styleable.ImageLayout_imageWidth, -1);
112 | imageHeight = a.getInteger(R.styleable.ImageLayout_imageHeight, -1);
113 |
114 | int fitMode = a.getInt(R.styleable.ImageLayout_fit, this.fitMode);
115 | setFitMode(fitMode);
116 |
117 | int gravity = a.getInt(R.styleable.ImageLayout_android_gravity, this.gravity);
118 | setGravity(gravity);
119 | a.recycle();
120 | }
121 |
122 | /**
123 | * Determines how the background image is drawn
124 | * @param newValue Accepted values are {@link ImageLayout#FIT_BOTH}, {@link ImageLayout#FIT_AUTO},
125 | * {@link ImageLayout#FIT_VERTICAL} and {@link ImageLayout#FIT_HORIZONTAL}
126 | */
127 | public void setFitMode(int newValue) {
128 | if (fitter != null && fitMode == newValue) {
129 | return;
130 | }
131 | fitMode = newValue;
132 | rebuildFitter();
133 | }
134 |
135 | public void setGravity(int newValue) {
136 | if (fitter != null && gravity == newValue) {
137 | return;
138 | }
139 | if ((newValue & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) {
140 | newValue |= Gravity.CENTER_HORIZONTAL;
141 | }
142 | if ((newValue & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
143 | newValue |= Gravity.CENTER_VERTICAL;
144 | }
145 | gravity = newValue;
146 | rebuildFitter();
147 | }
148 |
149 | public int getFitMode() {
150 | return fitMode;
151 | }
152 |
153 | /**
154 | * Changes the background image and its layout dimensions.
155 | */
156 | public void setImageResource(int imageResource, int imageWidth, int imageHeight) {
157 | bitmap = extractBitmapFromDrawable(getResources().getDrawable(imageResource));
158 | bitmapSrcRect = bitmapRect(bitmap);
159 |
160 | this.imageWidth = imageWidth;
161 | this.imageHeight = imageHeight;
162 |
163 | rebuildFitter();
164 | }
165 |
166 | private static Bitmap extractBitmapFromDrawable(Drawable drawable) {
167 | return ((BitmapDrawable) drawable).getBitmap();
168 | }
169 |
170 | private static Rect bitmapRect(Bitmap bitmap) {
171 | return new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
172 | }
173 |
174 | private void rebuildFitter() {
175 | fitter = new ImageFitter(fitMode, gravity);
176 | requestLayout();
177 | invalidate();
178 | }
179 |
180 | private int transformWidthFromBitmapToView(int w) {
181 | float widthRatio = bitmapDestRect.width() / (float) imageWidth;
182 | return (int) (w * widthRatio);
183 | }
184 |
185 | private int transformHeightFromBitmapToView(int h) {
186 | float heightRatio = bitmapDestRect.height() / (float) imageHeight;
187 | return (int) (h * heightRatio);
188 | }
189 |
190 | private int transformXFromBitmapToView(int x) {
191 | float widthRatio = bitmapDestRect.width() / (float) imageWidth;
192 | return bitmapDestRect.left + (int) (x * widthRatio);
193 | }
194 |
195 | private int transformYFromBitmapToView(int y) {
196 | float heightRatio = bitmapDestRect.height() / (float) imageHeight;
197 | return bitmapDestRect.top + (int) (y * heightRatio);
198 | }
199 |
200 | @Override
201 | protected void onDraw(Canvas canvas) {
202 | canvas.drawBitmap(bitmap, bitmapSrcRect, bitmapDestRect, null);
203 | super.onDraw(canvas);
204 | }
205 |
206 | @Override
207 | protected void onLayout(boolean changed, int l, int t, int r, int b) {
208 | int N = getChildCount();
209 | for (int i = 0; i < N; ++i) {
210 | View child = getChildAt(i);
211 | LayoutParams layoutParams = (LayoutParams) child.getLayoutParams();
212 | child.layout(layoutParams.transformedRect.left, layoutParams.transformedRect.top, layoutParams.transformedRect.right, layoutParams.transformedRect.bottom);
213 | }
214 | }
215 |
216 | @Override
217 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
218 | int widthMode = MeasureSpec.getMode(widthMeasureSpec);
219 | int heightMode = MeasureSpec.getMode(heightMeasureSpec);
220 | int widthSpec = MeasureSpec.getSize(widthMeasureSpec);
221 | int width = widthSpec;
222 | int heightSpec = MeasureSpec.getSize(heightMeasureSpec);
223 | int height = heightSpec;
224 | boolean isExactWidth = widthMode == MeasureSpec.EXACTLY;
225 | boolean isExactHeight = heightMode == MeasureSpec.EXACTLY;
226 | float bitmapAspectRatio = (bitmap.getWidth() + getPaddingLeft() + getPaddingRight())
227 | / ((float)bitmap.getHeight() + getPaddingTop() + getPaddingBottom());
228 | if (isExactWidth && !isExactHeight) {
229 | height = (int)(width / bitmapAspectRatio);
230 | if (heightMode == MeasureSpec.AT_MOST && height > heightSpec) {
231 | height = heightSpec;
232 | }
233 | }
234 | else if (isExactHeight && !isExactWidth) {
235 | width = (int)(height * bitmapAspectRatio);
236 | if (widthMode == MeasureSpec.AT_MOST && width > widthSpec) {
237 | width = widthSpec;
238 | }
239 | }
240 | setMeasuredDimension(width, height);
241 |
242 | int effectiveWidth = width - getPaddingLeft() - getPaddingRight();
243 | int effectiveHeight = height - getPaddingTop() - getPaddingBottom();
244 | bitmapDestRect = fitter.fit(bitmap, effectiveWidth, effectiveHeight);
245 | adjustBitmapRectForPadding();
246 |
247 | int N = getChildCount();
248 | for (int i = 0; i < N; ++i) {
249 | View child = getChildAt(i);
250 | measureChild(child);
251 | }
252 | }
253 |
254 | private void measureChild(View child) {
255 | LayoutParams layoutParams = (LayoutParams) child.getLayoutParams();
256 | checkChildLayoutParams(layoutParams);
257 | int wspec = makeWidthSpec(layoutParams);
258 | int hspec = makeHeightSpec(layoutParams);
259 | child.measure(wspec, hspec);
260 | int left = 0, width = child.getMeasuredWidth();
261 | if (layoutParams.left != -1) {
262 | left = transformXFromBitmapToView(layoutParams.left);
263 | if (layoutParams.right != -1) {
264 | int right = transformXFromBitmapToView(layoutParams.right);
265 | width = right - left;
266 | }
267 | } else if (layoutParams.right != -1) {
268 | int right = transformXFromBitmapToView(layoutParams.right);
269 | left = right - width;
270 | } else if (layoutParams.centerX != -1) {
271 | int cx = transformXFromBitmapToView(layoutParams.centerX);
272 | left = cx - width / 2;
273 | }
274 |
275 | int top = 0, height = child.getMeasuredHeight();
276 | if (layoutParams.top != -1) {
277 | top = transformYFromBitmapToView(layoutParams.top);
278 | if (layoutParams.bottom != -1) {
279 | int bottom = transformYFromBitmapToView(layoutParams.bottom);
280 | height = bottom - top;
281 | }
282 | } else if (layoutParams.bottom != -1) {
283 | int bottom = transformYFromBitmapToView(layoutParams.bottom);
284 | top = bottom - height;
285 | } else if (layoutParams.centerY != -1) {
286 | int cy = transformYFromBitmapToView(layoutParams.centerY);
287 | top = cy - height / 2;
288 | }
289 | layoutParams.transformedRect.set(left, top, left + width, top + height);
290 | }
291 |
292 | private void adjustBitmapRectForPadding() {
293 | bitmapDestRect.left += getPaddingLeft();
294 | bitmapDestRect.right += getPaddingLeft();
295 | bitmapDestRect.top += getPaddingTop();
296 | bitmapDestRect.bottom += getPaddingTop();
297 | }
298 |
299 | private int makeHeightSpec(LayoutParams layoutParams) {
300 | int hspec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
301 | if (layoutParams.maxHeight != -1) {
302 | int height = transformHeightFromBitmapToView(layoutParams.maxHeight);
303 | hspec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
304 | } else if (layoutParams.height != LayoutParams.WRAP_CONTENT) {
305 | int height = transformHeightFromBitmapToView(layoutParams.height);
306 | hspec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
307 | }
308 | return hspec;
309 | }
310 |
311 | private int makeWidthSpec(LayoutParams layoutParams) {
312 | int wspec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
313 | if (layoutParams.maxWidth != -1) {
314 | int maxWidth = transformWidthFromBitmapToView(layoutParams.maxWidth);
315 | wspec = MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.AT_MOST);
316 | } else if (layoutParams.width != LayoutParams.WRAP_CONTENT) {
317 | int width = transformWidthFromBitmapToView(layoutParams.width);
318 | wspec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
319 | }
320 | return wspec;
321 | }
322 |
323 | private void checkChildLayoutParams(LayoutParams layoutParams) {
324 | }
325 |
326 | public static class LayoutParams extends ViewGroup.LayoutParams {
327 | // In image coords
328 | public int maxWidth = -1, maxHeight = -1;
329 | public int left = -1, top = -1, right = -1, bottom = -1;
330 | public int centerX = -1, centerY = -1;
331 | // In view coords
332 | Rect transformedRect = new Rect();
333 |
334 | public LayoutParams() {
335 | this(null, null);
336 | }
337 |
338 | public LayoutParams(Context c, AttributeSet attrs) {
339 | // We don't call super(c, attrs) to prevent the layout_width and
340 | // layout_height
341 | // attributes from being mandatory
342 | super(WRAP_CONTENT, WRAP_CONTENT);
343 |
344 | if (c == null || attrs == null) {
345 | return;
346 | }
347 |
348 | TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.ImageLayout_Layout);
349 |
350 | int N = a.getIndexCount();
351 | for (int i = 0; i < N; i++) {
352 | int attr = a.getIndex(i);
353 | switch (attr) {
354 | case R.styleable.ImageLayout_Layout_layout_left:
355 | left = a.getInt(attr, -1);
356 | break;
357 | case R.styleable.ImageLayout_Layout_layout_top:
358 | top = a.getInt(attr, -1);
359 | break;
360 | case R.styleable.ImageLayout_Layout_layout_right:
361 | right = a.getInt(attr, -1);
362 | break;
363 | case R.styleable.ImageLayout_Layout_layout_bottom:
364 | bottom = a.getInt(attr, -1);
365 | break;
366 | case R.styleable.ImageLayout_Layout_layout_centerX:
367 | centerX = a.getInt(attr, -1);
368 | break;
369 | case R.styleable.ImageLayout_Layout_layout_centerY:
370 | centerY = a.getInt(attr, -1);
371 | break;
372 | case R.styleable.ImageLayout_Layout_layout_width:
373 | width = a.getInt(attr, -1);
374 | break;
375 | case R.styleable.ImageLayout_Layout_layout_maxWidth:
376 | maxWidth = a.getInt(attr, -1);
377 | break;
378 | case R.styleable.ImageLayout_Layout_layout_height:
379 | height = a.getInt(attr, -1);
380 | break;
381 | case R.styleable.ImageLayout_Layout_layout_maxHeight:
382 | maxHeight = a.getInt(attr, -1);
383 | break;
384 | }
385 | }
386 | a.recycle();
387 | }
388 |
389 | LayoutParams(ViewGroup.LayoutParams source) {
390 | super(source);
391 | }
392 | }
393 |
394 | @Override
395 | public LayoutParams generateLayoutParams(AttributeSet attrs) {
396 | return new LayoutParams(getContext(), attrs);
397 | }
398 |
399 | @Override
400 | protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
401 | return new LayoutParams();
402 | }
403 |
404 | @Override
405 | protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
406 | return p instanceof LayoutParams;
407 | }
408 |
409 | @Override
410 | protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
411 | return new LayoutParams(p);
412 | }
413 | }
--------------------------------------------------------------------------------
/maven_push.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'maven'
2 | apply plugin: 'signing'
3 |
4 | def sonatypeRepositoryUrl
5 | if (isReleaseBuild()) {
6 | println 'RELEASE BUILD'
7 | sonatypeRepositoryUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
8 | } else {
9 | println 'DEBUG BUILD'
10 | sonatypeRepositoryUrl = "https://oss.sonatype.org/content/repositories/snapshots/"
11 | }
12 |
13 | afterEvaluate { project ->
14 | uploadArchives {
15 | repositories {
16 | mavenDeployer {
17 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
18 |
19 | pom.artifactId = POM_ARTIFACT_ID
20 |
21 | repository(url: sonatypeRepositoryUrl) {
22 | authentication(userName: nexusUsername, password: nexusPassword)
23 | }
24 |
25 | pom.project {
26 | name POM_NAME
27 | packaging POM_PACKAGING
28 | description POM_DESCRIPTION
29 | url POM_URL
30 |
31 | scm {
32 | url POM_SCM_URL
33 | connection POM_SCM_CONNECTION
34 | developerConnection POM_SCM_DEV_CONNECTION
35 | }
36 |
37 | licenses {
38 | license {
39 | name POM_LICENCE_NAME
40 | url POM_LICENCE_URL
41 | distribution POM_LICENCE_DIST
42 | }
43 | }
44 |
45 | developers {
46 | developer {
47 | id POM_DEVELOPER_ID
48 | name POM_DEVELOPER_NAME
49 | }
50 | }
51 | }
52 | }
53 | }
54 | }
55 |
56 | signing {
57 | required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
58 | sign configurations.archives
59 | }
60 |
61 | task androidJavadocs(type: Javadoc) {
62 | source = android.sourceSets.main.allJava
63 | }
64 |
65 | task androidJavadocsJar(type: Jar) {
66 | classifier = 'javadoc'
67 | //basename = artifact_id
68 | from androidJavadocs.destinationDir
69 | }
70 |
71 | task androidSourcesJar(type: Jar) {
72 | classifier = 'sources'
73 | //basename = artifact_id
74 | from android.sourceSets.main.allSource
75 | }
76 |
77 | artifacts {
78 | //archives packageReleaseJar
79 | archives androidSourcesJar
80 | archives androidJavadocsJar
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/sample/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
9 |
10 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
22 |
23 |
27 |
28 |
31 |
32 |
35 |
36 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/sample/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'android'
2 |
3 | dependencies {
4 | compile project(':library')
5 | }
6 |
7 | android {
8 | compileSdkVersion Integer.parseInt(project.ANDROID_COMPILE_SDK_VERSION)
9 | buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION
10 |
11 | defaultConfig {
12 | minSdkVersion Integer.parseInt(project.ANDROID_MIN_SDK)
13 | targetSdkVersion Integer.parseInt(project.ANDROID_TARGET_SDK_VERSION)
14 | versionName project.VERSION_NAME
15 | versionCode Integer.parseInt(project.VERSION_CODE)
16 | }
17 |
18 | signingConfigs { release }
19 |
20 | buildTypes {
21 | release {
22 | signingConfig signingConfigs.release
23 | }
24 | }
25 |
26 | sourceSets {
27 | main {
28 | manifest.srcFile 'AndroidManifest.xml'
29 | java.srcDirs = ['src']
30 | res.srcDirs = ['res']
31 | }
32 | }
33 |
34 | lintOptions {
35 | abortOnError false
36 | }
37 | }
38 |
39 |
40 | File propFile = file('signing.properties');
41 | if (propFile.exists()) {
42 | def Properties props = new Properties()
43 | props.load(new FileInputStream(propFile))
44 |
45 | if (props.containsKey('STORE_FILE') && props.containsKey('STORE_PASSWORD') &&
46 | props.containsKey('KEY_ALIAS') && props.containsKey('KEY_PASSWORD')) {
47 | android.signingConfigs.release.storeFile = file(props['STORE_FILE'])
48 | android.signingConfigs.release.storePassword = props['STORE_PASSWORD']
49 | android.signingConfigs.release.keyAlias = props['KEY_ALIAS']
50 | android.signingConfigs.release.keyPassword = props['KEY_PASSWORD']
51 | } else {
52 | android.buildTypes.release.signingConfig = null
53 | }
54 | } else {
55 | android.buildTypes.release.signingConfig = null
56 | }
57 |
--------------------------------------------------------------------------------
/sample/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-17
15 | android.library=false
16 | android.library.reference.1=../library
17 |
--------------------------------------------------------------------------------
/sample/res/drawable-hdpi/boroughs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelPeinado/ImageLayout/6be0b5dc361ca1e1039cd8c40ad63721b7a1a154/sample/res/drawable-hdpi/boroughs.png
--------------------------------------------------------------------------------
/sample/res/drawable-hdpi/curiosity.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelPeinado/ImageLayout/6be0b5dc361ca1e1039cd8c40ad63721b7a1a154/sample/res/drawable-hdpi/curiosity.jpg
--------------------------------------------------------------------------------
/sample/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelPeinado/ImageLayout/6be0b5dc361ca1e1039cd8c40ad63721b7a1a154/sample/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/res/drawable-hdpi/manhattan.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelPeinado/ImageLayout/6be0b5dc361ca1e1039cd8c40ad63721b7a1a154/sample/res/drawable-hdpi/manhattan.jpg
--------------------------------------------------------------------------------
/sample/res/drawable-mdpi/boroughs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelPeinado/ImageLayout/6be0b5dc361ca1e1039cd8c40ad63721b7a1a154/sample/res/drawable-mdpi/boroughs.png
--------------------------------------------------------------------------------
/sample/res/drawable-mdpi/curiosity.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelPeinado/ImageLayout/6be0b5dc361ca1e1039cd8c40ad63721b7a1a154/sample/res/drawable-mdpi/curiosity.jpg
--------------------------------------------------------------------------------
/sample/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelPeinado/ImageLayout/6be0b5dc361ca1e1039cd8c40ad63721b7a1a154/sample/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/res/drawable-mdpi/manhattan.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelPeinado/ImageLayout/6be0b5dc361ca1e1039cd8c40ad63721b7a1a154/sample/res/drawable-mdpi/manhattan.jpg
--------------------------------------------------------------------------------
/sample/res/drawable-xhdpi/boroughs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelPeinado/ImageLayout/6be0b5dc361ca1e1039cd8c40ad63721b7a1a154/sample/res/drawable-xhdpi/boroughs.png
--------------------------------------------------------------------------------
/sample/res/drawable-xhdpi/curiosity.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelPeinado/ImageLayout/6be0b5dc361ca1e1039cd8c40ad63721b7a1a154/sample/res/drawable-xhdpi/curiosity.jpg
--------------------------------------------------------------------------------
/sample/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelPeinado/ImageLayout/6be0b5dc361ca1e1039cd8c40ad63721b7a1a154/sample/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/res/drawable-xhdpi/manhattan.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelPeinado/ImageLayout/6be0b5dc361ca1e1039cd8c40ad63721b7a1a154/sample/res/drawable-xhdpi/manhattan.jpg
--------------------------------------------------------------------------------
/sample/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ManuelPeinado/ImageLayout/6be0b5dc361ca1e1039cd8c40ad63721b7a1a154/sample/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/res/layout/activity_add_children_programmatically.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
--------------------------------------------------------------------------------
/sample/res/layout/activity_basic_usage.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
26 |
27 |
33 |
34 |
40 |
41 |
47 |
48 |
54 |
55 |
--------------------------------------------------------------------------------
/sample/res/layout/activity_change_image_dynamically.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
21 |
22 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/sample/res/layout/activity_fit_attribute.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
--------------------------------------------------------------------------------
/sample/res/layout/activity_home.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
--------------------------------------------------------------------------------
/sample/res/layout/activity_horizontal_scroll_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
14 |
19 | >
20 |
--------------------------------------------------------------------------------
/sample/res/menu/activity_fit_attribute.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/sample/res/values-large/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 18dp
5 | 24dp
6 | 36dp
7 |
8 |
--------------------------------------------------------------------------------
/sample/res/values-small/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 9dp
4 | 12dp
5 | 18dp
6 |
7 |
--------------------------------------------------------------------------------
/sample/res/values-v11/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/sample/res/values-v14/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/sample/res/values-xlarge/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 24dp
5 | 32dp
6 | 48dp
7 |
8 |
--------------------------------------------------------------------------------
/sample/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 12dp
5 | 16dp
6 | 24dp
7 |
8 |
--------------------------------------------------------------------------------
/sample/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | ImageLayout Sample
4 | Manhattan
5 | Queens
6 | Brooklyn
7 | Bronx
8 | Staten Island
9 | Choose a Borough
10 | MastCam
11 | You have selected
12 | New York City
13 | Curiosity Instruments
14 | Fit modes
15 | Fit vertical
16 | Fit horizontal
17 | Fit both
18 | Fit auto
19 | Horizontal scroll
20 | Change image
21 | Harlem>
22 |
23 |
--------------------------------------------------------------------------------
/sample/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 |
16 |
17 |
20 |
21 |
--------------------------------------------------------------------------------
/sample/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
19 |
20 |
--------------------------------------------------------------------------------
/sample/src/com/manuelpeinado/imagelayout/demo/ActivityInfo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Manuel Peinado
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.manuelpeinado.imagelayout.demo;
17 |
18 | import android.app.Activity;
19 |
20 | public class ActivityInfo {
21 | public Class extends Activity> activityClass;
22 | public int titleResourceId;
23 |
24 | public ActivityInfo(Class extends Activity> activityClass, int titleResourceId) {
25 | this.activityClass = activityClass;
26 | this.titleResourceId = titleResourceId;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/sample/src/com/manuelpeinado/imagelayout/demo/AddChildrenProgrammaticallyActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Manuel Peinado
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.manuelpeinado.imagelayout.demo;
17 |
18 | import android.app.Activity;
19 | import android.os.Bundle;
20 | import android.util.TypedValue;
21 | import android.view.View;
22 | import android.view.View.OnClickListener;
23 | import android.widget.Button;
24 | import android.widget.Toast;
25 |
26 | import com.manuelpeinado.imagelayout.ImageLayout;
27 |
28 | /**
29 | * This activity demonstrates that it's also possible to add children to
30 | * an ImageLayout from Java code
31 | */
32 | public class AddChildrenProgrammaticallyActivity extends Activity implements OnClickListener {
33 |
34 | @Override
35 | protected void onCreate(Bundle savedInstanceState) {
36 | super.onCreate(savedInstanceState);
37 | setContentView(R.layout.activity_add_children_programmatically);
38 |
39 | ImageLayout imageLayout = (ImageLayout) findViewById(R.id.image_layout);
40 | Button mastCamButton = new Button(this);
41 | ImageLayout.LayoutParams layoutParams = new ImageLayout.LayoutParams();
42 | layoutParams.right = 110;
43 | layoutParams.centerY = 80;
44 | mastCamButton.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(R.dimen.small_text));
45 | mastCamButton.setText(R.string.mastcam);
46 | mastCamButton.setOnClickListener(this);
47 | imageLayout.addView(mastCamButton, layoutParams);
48 | }
49 |
50 | @Override
51 | public void onClick(View view) {
52 | String msg = getString(R.string.you_have_selected);
53 | msg = msg + ": " + ((Button)view).getText();
54 | Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/sample/src/com/manuelpeinado/imagelayout/demo/BasicUsageActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Manuel Peinado
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.manuelpeinado.imagelayout.demo;
17 |
18 | import android.app.Activity;
19 | import android.os.Bundle;
20 |
21 | /**
22 | * This activity showcases the most common way to use the ImageLayout class,
23 | * in which all the children are specified in XML
24 | */
25 | public class BasicUsageActivity extends Activity {
26 |
27 | @Override
28 | protected void onCreate(Bundle savedInstanceState) {
29 | super.onCreate(savedInstanceState);
30 | setContentView(R.layout.activity_basic_usage);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/sample/src/com/manuelpeinado/imagelayout/demo/ChangeImageDynamicallyActivity.java:
--------------------------------------------------------------------------------
1 | package com.manuelpeinado.imagelayout.demo;
2 |
3 | /*
4 | * Copyright (C) 2014 Manuel Peinado
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import android.app.Activity;
20 | import android.os.Bundle;
21 | import android.util.TypedValue;
22 | import android.view.Gravity;
23 | import android.view.View;
24 | import android.widget.Button;
25 |
26 | import com.manuelpeinado.imagelayout.ImageLayout;
27 |
28 | public class ChangeImageDynamicallyActivity extends Activity {
29 |
30 | private ImageLayout imageLayout;
31 |
32 | @Override
33 | protected void onCreate(Bundle savedInstanceState) {
34 | super.onCreate(savedInstanceState);
35 | setContentView(R.layout.activity_change_image_dynamically);
36 | imageLayout = (ImageLayout)findViewById(R.id.image_layout);
37 | }
38 |
39 | public void onButtonClick(View view) {
40 | imageLayout.setImageResource(R.drawable.manhattan, 800, 1449);
41 | imageLayout.setGravity(Gravity.CENTER);
42 | imageLayout.setPadding(0, -100, 0, -100);
43 | imageLayout.setFitMode(ImageLayout.FIT_VERTICAL);
44 | imageLayout.removeAllViews();
45 |
46 | Button button = new Button(this);
47 | ImageLayout.LayoutParams layoutParams = new ImageLayout.LayoutParams();
48 | layoutParams.left = 243;
49 | layoutParams.top = 297;
50 | layoutParams.right = 432;
51 | layoutParams.bottom = 405;
52 | button.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(R.dimen.normal_text));
53 | button.setText(R.string.harlem);
54 | imageLayout.addView(button, layoutParams);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/sample/src/com/manuelpeinado/imagelayout/demo/FitAttributeActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Manuel Peinado
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.manuelpeinado.imagelayout.demo;
17 |
18 | import android.app.Activity;
19 | import android.os.Bundle;
20 | import android.view.Menu;
21 | import android.view.MenuItem;
22 |
23 | import com.manuelpeinado.imagelayout.ImageLayout;
24 |
25 | /**
26 | * This activity illustrates the different values accepted by the
27 | * "custom:fit" attribute
28 | */
29 | public class FitAttributeActivity extends Activity {
30 |
31 | private ImageLayout imageLayout;
32 |
33 | @Override
34 | protected void onCreate(Bundle savedInstanceState) {
35 | super.onCreate(savedInstanceState);
36 | setContentView(R.layout.activity_fit_attribute);
37 | imageLayout = (ImageLayout) findViewById(R.id.image_layout);
38 | initFitMode(savedInstanceState);
39 | }
40 |
41 | private void initFitMode(Bundle savedInstanceState) {
42 | int fitMode = imageLayout.getFitMode();
43 | if (savedInstanceState != null) {
44 | fitMode = savedInstanceState.getInt("fitMode", fitMode);
45 | }
46 | setFitMode(fitMode);
47 | }
48 |
49 | @Override
50 | public boolean onCreateOptionsMenu(Menu menu) {
51 | getMenuInflater().inflate(R.menu.activity_fit_attribute, menu);
52 | return true;
53 | }
54 |
55 | @Override
56 | public boolean onOptionsItemSelected(MenuItem item) {
57 | if (item.getItemId() == R.id.fit_vertical) {
58 | setFitMode(ImageLayout.FIT_VERTICAL);
59 | return true;
60 | }
61 | if (item.getItemId() == R.id.fit_horizontal) {
62 | setFitMode(ImageLayout.FIT_HORIZONTAL);
63 | return true;
64 | }
65 | if (item.getItemId() == R.id.fit_auto) {
66 | setFitMode(ImageLayout.FIT_AUTO);
67 | return true;
68 | }
69 | if (item.getItemId() == R.id.fit_both) {
70 | setFitMode(ImageLayout.FIT_BOTH);
71 | return true;
72 | }
73 | return false;
74 | }
75 |
76 | private void setFitMode(int fitMode) {
77 | imageLayout.setFitMode(fitMode);
78 | updateTitle();
79 | }
80 |
81 | private void updateTitle() {
82 | switch (imageLayout.getFitMode()) {
83 | case ImageLayout.FIT_VERTICAL:
84 | setTitle(R.string.fit_vertical);
85 | return;
86 | case ImageLayout.FIT_HORIZONTAL:
87 | setTitle(R.string.fit_horizontal);
88 | return;
89 | case ImageLayout.FIT_AUTO:
90 | setTitle(R.string.fit_auto);
91 | return;
92 | case ImageLayout.FIT_BOTH:
93 | setTitle(R.string.fit_both);
94 | return;
95 | }
96 | }
97 |
98 | @Override
99 | protected void onSaveInstanceState(Bundle outState) {
100 | outState.putInt("fitMode", imageLayout.getFitMode());
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/sample/src/com/manuelpeinado/imagelayout/demo/HomeActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Manuel Peinado
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.manuelpeinado.imagelayout.demo;
17 |
18 | import java.util.Arrays;
19 | import java.util.List;
20 |
21 | import android.app.Activity;
22 | import android.app.ListActivity;
23 | import android.content.Intent;
24 | import android.os.Bundle;
25 | import android.view.View;
26 | import android.widget.ArrayAdapter;
27 | import android.widget.ListView;
28 |
29 | /**
30 | * This activity serves as the launcher for the different samples
31 | */
32 | public class HomeActivity extends ListActivity {
33 | private List activitiesInfo = Arrays.asList(
34 | new ActivityInfo(BasicUsageActivity.class, R.string.activity_title_basic_usage),
35 | new ActivityInfo(AddChildrenProgrammaticallyActivity.class, R.string.activity_title_add_children_programmatically),
36 | new ActivityInfo(FitAttributeActivity.class, R.string.activity_title_fit_attribute),
37 | new ActivityInfo(HorizontalScrollViewActivity.class, R.string.activity_title_horizontal_scroll_view),
38 | new ActivityInfo(ChangeImageDynamicallyActivity.class, R.string.activity_title_change_image_dynamically));
39 |
40 | @Override
41 | protected void onCreate(Bundle savedInstanceState) {
42 | super.onCreate(savedInstanceState);
43 | setContentView(R.layout.activity_home);
44 | String[] titles = getActivityTitles();
45 | setListAdapter(new ArrayAdapter(
46 | this, android.R.layout.simple_list_item_1, android.R.id.text1, titles));
47 | }
48 |
49 | @Override
50 | protected void onListItemClick(ListView l, View v, int position, long id) {
51 | Class extends Activity> class_ = activitiesInfo.get(position).activityClass;
52 | Intent intent = new Intent(this, class_);
53 | startActivity(intent);
54 | }
55 |
56 | private String[] getActivityTitles() {
57 | String[] result = new String[activitiesInfo.size()];
58 | int i = 0;
59 | for (ActivityInfo info : activitiesInfo) {
60 | result[i++] = getString(info.titleResourceId);
61 | }
62 | return result;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/sample/src/com/manuelpeinado/imagelayout/demo/HorizontalScrollViewActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Manuel Peinado
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.manuelpeinado.imagelayout.demo;
17 |
18 | import android.app.Activity;
19 | import android.os.Bundle;
20 | import android.view.View;
21 | import android.widget.Button;
22 | import android.widget.Toast;
23 |
24 | public class HorizontalScrollViewActivity extends Activity {
25 |
26 | @Override
27 | protected void onCreate(Bundle savedInstanceState) {
28 | super.onCreate(savedInstanceState);
29 | setContentView(R.layout.activity_horizontal_scroll_view);
30 | }
31 |
32 | public void onButtonClick(View view) {
33 | String msg = getString(R.string.you_have_selected);
34 | msg = msg + ": " + ((Button)view).getText();
35 | Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':library'
2 | include ':sample'
3 |
--------------------------------------------------------------------------------