Skip to content

Commit 0de219a

Browse files
committed
Adding libraries manually
1 parent 42e69a1 commit 0de219a

File tree

11 files changed

+733
-0
lines changed

11 files changed

+733
-0
lines changed

iosalert/libs/annotation-1.0.0.jar

-24.8 KB
Binary file not shown.

iosalert/libs/blurview-1.6.2.aar

-12.9 KB
Binary file not shown.
Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
package com.maliotis.iosalert.blurview;
2+
3+
import android.graphics.Bitmap;
4+
import android.graphics.Canvas;
5+
import android.graphics.Color;
6+
import android.graphics.Paint;
7+
import android.graphics.drawable.Drawable;
8+
import android.os.Build;
9+
import android.support.annotation.ColorInt;
10+
import android.support.annotation.NonNull;
11+
import android.support.annotation.Nullable;
12+
import android.view.View;
13+
import android.view.ViewGroup;
14+
import android.view.ViewTreeObserver;
15+
16+
/**
17+
* Blur Controller that handles all blur logic for the attached View.
18+
* It honors View size changes, View animation and Visibility changes.
19+
* <p>
20+
* The basic idea is to draw the view hierarchy on a bitmap, excluding the attached View,
21+
* then blur and draw it on the system Canvas.
22+
* <p>
23+
* It uses {@link ViewTreeObserver.OnPreDrawListener} to detect when
24+
* blur should be updated.
25+
* <p>
26+
* Blur is done on the main thread.
27+
*/
28+
final class BlockingBlurController implements BlurController {
29+
30+
// Bitmap size should be divisible by ROUNDING_VALUE to meet stride requirement.
31+
// This will help avoiding an extra bitmap allocation when passing the bitmap to RenderScript for blur.
32+
// Usually it's 16, but on Samsung devices it's 64 for some reason.
33+
private static final int ROUNDING_VALUE = 64;
34+
@ColorInt
35+
static final int TRANSPARENT = 0;
36+
37+
private final float scaleFactor = DEFAULT_SCALE_FACTOR;
38+
private float blurRadius = DEFAULT_BLUR_RADIUS;
39+
private float roundingWidthScaleFactor = 1f;
40+
private float roundingHeightScaleFactor = 1f;
41+
42+
private BlurAlgorithm blurAlgorithm;
43+
private Canvas internalCanvas;
44+
private Bitmap internalBitmap;
45+
46+
@SuppressWarnings("WeakerAccess")
47+
final View blurView;
48+
private int overlayColor;
49+
private final ViewGroup rootView;
50+
private final int[] rootLocation = new int[2];
51+
private final int[] blurViewLocation = new int[2];
52+
53+
private final ViewTreeObserver.OnPreDrawListener drawListener = new ViewTreeObserver.OnPreDrawListener() {
54+
@Override
55+
public boolean onPreDraw() {
56+
// Not invalidating a View here, just updating the Bitmap.
57+
// This relies on the HW accelerated bitmap drawing behavior in Android
58+
// If the bitmap was drawn on HW accelerated canvas, it holds a reference to it and on next
59+
// drawing pass the updated content of the bitmap will be rendered on the screen
60+
61+
updateBlur();
62+
return true;
63+
}
64+
};
65+
66+
private boolean blurEnabled = true;
67+
private boolean initialized;
68+
69+
@Nullable
70+
private Drawable frameClearDrawable;
71+
private boolean hasFixedTransformationMatrix;
72+
private final Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG);
73+
74+
/**
75+
* @param blurView View which will draw it's blurred underlying content
76+
* @param rootView Root View where blurView's underlying content starts drawing.
77+
* Can be Activity's root content layout (android.R.id.content)
78+
* or some of your custom root layouts.
79+
*/
80+
BlockingBlurController(@NonNull View blurView, @NonNull ViewGroup rootView, @ColorInt int overlayColor) {
81+
this.rootView = rootView;
82+
this.blurView = blurView;
83+
this.overlayColor = overlayColor;
84+
this.blurAlgorithm = new NoOpBlurAlgorithm();
85+
86+
int measuredWidth = blurView.getMeasuredWidth();
87+
int measuredHeight = blurView.getMeasuredHeight();
88+
89+
if (isZeroSized(measuredWidth, measuredHeight)) {
90+
deferBitmapCreation();
91+
return;
92+
}
93+
94+
init(measuredWidth, measuredHeight);
95+
}
96+
97+
private int downScaleSize(float value) {
98+
return (int) Math.ceil(value / scaleFactor);
99+
}
100+
101+
/**
102+
* Rounds a value to the nearest divisible by {@link #ROUNDING_VALUE} to meet stride requirement
103+
*/
104+
private int roundSize(int value) {
105+
if (value % ROUNDING_VALUE == 0) {
106+
return value;
107+
}
108+
return value - (value % ROUNDING_VALUE) + ROUNDING_VALUE;
109+
}
110+
111+
@SuppressWarnings("WeakerAccess")
112+
void init(int measuredWidth, int measuredHeight) {
113+
if (isZeroSized(measuredWidth, measuredHeight)) {
114+
blurView.setWillNotDraw(true);
115+
return;
116+
}
117+
118+
blurView.setWillNotDraw(false);
119+
allocateBitmap(measuredWidth, measuredHeight);
120+
internalCanvas = new Canvas(internalBitmap);
121+
initialized = true;
122+
123+
if (hasFixedTransformationMatrix) {
124+
setupInternalCanvasMatrix();
125+
}
126+
}
127+
128+
private boolean isZeroSized(int measuredWidth, int measuredHeight) {
129+
return downScaleSize(measuredHeight) == 0 || downScaleSize(measuredWidth) == 0;
130+
}
131+
132+
@SuppressWarnings("WeakerAccess")
133+
void updateBlur() {
134+
if (!blurEnabled || !initialized) {
135+
return;
136+
}
137+
138+
if (frameClearDrawable == null) {
139+
internalBitmap.eraseColor(Color.TRANSPARENT);
140+
} else {
141+
frameClearDrawable.draw(internalCanvas);
142+
}
143+
144+
if (hasFixedTransformationMatrix) {
145+
rootView.draw(internalCanvas);
146+
} else {
147+
internalCanvas.save();
148+
setupInternalCanvasMatrix();
149+
rootView.draw(internalCanvas);
150+
internalCanvas.restore();
151+
}
152+
153+
blurAndSave();
154+
}
155+
156+
/**
157+
* Deferring initialization until view is laid out
158+
*/
159+
private void deferBitmapCreation() {
160+
blurView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
161+
@Override
162+
public void onGlobalLayout() {
163+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
164+
blurView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
165+
} else {
166+
legacyRemoveOnGlobalLayoutListener();
167+
}
168+
169+
int measuredWidth = blurView.getMeasuredWidth();
170+
int measuredHeight = blurView.getMeasuredHeight();
171+
172+
init(measuredWidth, measuredHeight);
173+
}
174+
175+
@SuppressWarnings("deprecation")
176+
void legacyRemoveOnGlobalLayoutListener() {
177+
blurView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
178+
}
179+
});
180+
}
181+
182+
private void allocateBitmap(int measuredWidth, int measuredHeight) {
183+
int nonRoundedScaledWidth = downScaleSize(measuredWidth);
184+
int nonRoundedScaledHeight = downScaleSize(measuredHeight);
185+
186+
int scaledWidth = roundSize(nonRoundedScaledWidth);
187+
int scaledHeight = roundSize(nonRoundedScaledHeight);
188+
189+
roundingHeightScaleFactor = (float) nonRoundedScaledHeight / scaledHeight;
190+
roundingWidthScaleFactor = (float) nonRoundedScaledWidth / scaledWidth;
191+
192+
internalBitmap = Bitmap.createBitmap(scaledWidth, scaledHeight, blurAlgorithm.getSupportedBitmapConfig());
193+
}
194+
195+
/**
196+
* Set up matrix to draw starting from blurView's position
197+
*/
198+
private void setupInternalCanvasMatrix() {
199+
rootView.getLocationOnScreen(rootLocation);
200+
blurView.getLocationOnScreen(blurViewLocation);
201+
202+
int left = blurViewLocation[0] - rootLocation[0];
203+
int top = blurViewLocation[1] - rootLocation[1];
204+
205+
float scaleFactorX = scaleFactor * roundingWidthScaleFactor;
206+
float scaleFactorY = scaleFactor * roundingHeightScaleFactor;
207+
208+
float scaledLeftPosition = -left / scaleFactorX;
209+
float scaledTopPosition = -top / scaleFactorY;
210+
211+
internalCanvas.translate(scaledLeftPosition, scaledTopPosition);
212+
internalCanvas.scale(1 / scaleFactorX, 1 / scaleFactorY);
213+
}
214+
215+
@Override
216+
public boolean draw(Canvas canvas) {
217+
if (!blurEnabled || !initialized) {
218+
return true;
219+
}
220+
// Not blurring own children
221+
if (canvas == internalCanvas) {
222+
return false;
223+
}
224+
225+
updateBlur();
226+
227+
canvas.save();
228+
canvas.scale(scaleFactor * roundingWidthScaleFactor, scaleFactor * roundingHeightScaleFactor);
229+
canvas.drawBitmap(internalBitmap, 0, 0, paint);
230+
canvas.restore();
231+
232+
if (overlayColor != TRANSPARENT) {
233+
canvas.drawColor(overlayColor);
234+
}
235+
return true;
236+
}
237+
238+
private void blurAndSave() {
239+
internalBitmap = blurAlgorithm.blur(internalBitmap, blurRadius);
240+
if (!blurAlgorithm.canModifyBitmap()) {
241+
internalCanvas.setBitmap(internalBitmap);
242+
}
243+
}
244+
245+
@Override
246+
public void updateBlurViewSize() {
247+
int measuredWidth = blurView.getMeasuredWidth();
248+
int measuredHeight = blurView.getMeasuredHeight();
249+
250+
init(measuredWidth, measuredHeight);
251+
}
252+
253+
@Override
254+
public void destroy() {
255+
setBlurAutoUpdate(false);
256+
blurAlgorithm.destroy();
257+
initialized = false;
258+
}
259+
260+
@Override
261+
public BlurViewFacade setBlurRadius(float radius) {
262+
this.blurRadius = radius;
263+
return this;
264+
}
265+
266+
@Override
267+
public BlurViewFacade setBlurAlgorithm(BlurAlgorithm algorithm) {
268+
this.blurAlgorithm = algorithm;
269+
return this;
270+
}
271+
272+
@Override
273+
public BlurViewFacade setFrameClearDrawable(@Nullable Drawable frameClearDrawable) {
274+
this.frameClearDrawable = frameClearDrawable;
275+
return this;
276+
}
277+
278+
@Override
279+
public BlurViewFacade setBlurEnabled(boolean enabled) {
280+
this.blurEnabled = enabled;
281+
setBlurAutoUpdate(enabled);
282+
blurView.invalidate();
283+
return this;
284+
}
285+
286+
public BlurViewFacade setBlurAutoUpdate(final boolean enabled) {
287+
blurView.getViewTreeObserver().removeOnPreDrawListener(drawListener);
288+
if (enabled) {
289+
blurView.getViewTreeObserver().addOnPreDrawListener(drawListener);
290+
}
291+
return this;
292+
}
293+
294+
@Override
295+
public BlurViewFacade setHasFixedTransformationMatrix(boolean hasFixedTransformationMatrix) {
296+
this.hasFixedTransformationMatrix = hasFixedTransformationMatrix;
297+
return this;
298+
}
299+
300+
@Override
301+
public BlurViewFacade setOverlayColor(int overlayColor) {
302+
if (this.overlayColor != overlayColor) {
303+
this.overlayColor = overlayColor;
304+
blurView.invalidate();
305+
}
306+
return this;
307+
}
308+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.maliotis.iosalert.blurview;
2+
3+
import android.graphics.Bitmap;
4+
import android.support.annotation.NonNull;
5+
6+
public interface BlurAlgorithm {
7+
/**
8+
* @param bitmap bitmap to be blurred
9+
* @param blurRadius blur radius
10+
* @return blurred bitmap
11+
*/
12+
Bitmap blur(Bitmap bitmap, float blurRadius);
13+
14+
/**
15+
* Frees allocated resources
16+
*/
17+
void destroy();
18+
19+
/**
20+
* @return true if this algorithm returns the same instance of bitmap as it accepted
21+
* false if it creates a new instance.
22+
* <p>
23+
* If you return false from this method, you'll be responsible to swap bitmaps in your
24+
* {@link BlurAlgorithm#blur(Bitmap, float)} implementation
25+
* (assign input bitmap to your field and return the instance algorithm just blurred).
26+
*/
27+
boolean canModifyBitmap();
28+
29+
/**
30+
* Retrieve the {@link Bitmap.Config} on which the {@link BlurAlgorithm}
31+
* can actually work.
32+
*
33+
* @return bitmap config supported by the given blur algorithm.
34+
*/
35+
@NonNull
36+
Bitmap.Config getSupportedBitmapConfig();
37+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.maliotis.iosalert.blurview;
2+
3+
import android.graphics.Canvas;
4+
5+
interface BlurController extends BlurViewFacade {
6+
7+
float DEFAULT_SCALE_FACTOR = 8f;
8+
float DEFAULT_BLUR_RADIUS = 16f;
9+
10+
/**
11+
* Draws blurred content on given canvas
12+
*
13+
* @return true if BlurView should proceed with drawing itself and its children
14+
*/
15+
boolean draw(Canvas canvas);
16+
17+
/**
18+
* Must be used to notify Controller when BlurView's size has changed
19+
*/
20+
void updateBlurViewSize();
21+
22+
/**
23+
* Frees allocated resources
24+
*/
25+
void destroy();
26+
}

0 commit comments

Comments
 (0)