Skip to content

Commit 0eeb157

Browse files
committed
v 1.1.4
1 parent a93ef63 commit 0eeb157

9 files changed

Lines changed: 369 additions & 10 deletions

File tree

headerview/build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ android {
77
defaultConfig {
88
minSdkVersion 8
99
targetSdkVersion 23
10-
versionCode 5
11-
versionName "1.1.3"
10+
versionCode 6
11+
versionName "1.1.4"
1212
}
1313
buildTypes {
1414
release {
@@ -21,7 +21,7 @@ android {
2121
userOrg = 'raphaelbussa'
2222
groupId = 'rebus'
2323
artifactId = 'header-view'
24-
publishVersion = '1.1.3'
24+
publishVersion = '1.1.4'
2525
}
2626

2727
}

headerview/src/main/java/rebus/header/view/AvatarView.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import android.graphics.drawable.Drawable;
3737
import android.widget.ImageView;
3838

39+
@Deprecated
3940
public class AvatarView extends ImageView{
4041

4142
public AvatarView(Context context) {
Lines changed: 330 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
/*
2+
* Copyright 2014 Google Inc. All rights reserved.
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+
* The original is from Google you can find here:
17+
* https://github.com/google/iosched/blob/master/android/src/main/java/com/google/samples/apps/iosched/ui/widget/BezelImageView.java
18+
*
19+
* Modified and improved with additional functionality by Mike Penz
20+
*/
21+
22+
package rebus.header.view;
23+
24+
import android.annotation.TargetApi;
25+
import android.content.Context;
26+
import android.content.res.TypedArray;
27+
import android.graphics.Bitmap;
28+
import android.graphics.Canvas;
29+
import android.graphics.Color;
30+
import android.graphics.ColorFilter;
31+
import android.graphics.ColorMatrix;
32+
import android.graphics.ColorMatrixColorFilter;
33+
import android.graphics.Outline;
34+
import android.graphics.Paint;
35+
import android.graphics.PorterDuff;
36+
import android.graphics.PorterDuffColorFilter;
37+
import android.graphics.PorterDuffXfermode;
38+
import android.graphics.Rect;
39+
import android.graphics.RectF;
40+
import android.graphics.drawable.Drawable;
41+
import android.os.Build;
42+
import android.util.AttributeSet;
43+
import android.view.MotionEvent;
44+
import android.view.View;
45+
import android.view.ViewOutlineProvider;
46+
import android.widget.ImageView;
47+
48+
49+
/**
50+
* Created by raphaelbussa on 26/03/16.
51+
*/
52+
public class BezelImageView extends ImageView {
53+
private Paint mBlackPaint;
54+
private Paint mMaskedPaint;
55+
56+
private Rect mBounds;
57+
private RectF mBoundsF;
58+
59+
private Drawable mMaskDrawable;
60+
private boolean mDrawCircularShadow = true;
61+
62+
private ColorMatrixColorFilter mDesaturateColorFilter;
63+
64+
private int mSelectorAlpha = 150;
65+
private int mSelectorColor;
66+
private ColorFilter mSelectorFilter;
67+
68+
private boolean mCacheValid = false;
69+
private Bitmap mCacheBitmap;
70+
private int mCachedWidth;
71+
private int mCachedHeight;
72+
73+
private boolean isPressed = false;
74+
private boolean isSelected;
75+
76+
public BezelImageView(Context context) {
77+
this(context, null);
78+
}
79+
80+
public BezelImageView(Context context, AttributeSet attrs) {
81+
this(context, attrs, 0);
82+
}
83+
84+
public BezelImageView(Context context, AttributeSet attrs, int defStyle) {
85+
super(context, attrs, defStyle);
86+
87+
// Attribute initialization
88+
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BezelImageView, defStyle, R.style.BezelImageView);
89+
90+
mMaskDrawable = a.getDrawable(R.styleable.BezelImageView_biv_maskDrawable);
91+
if (mMaskDrawable != null) {
92+
mMaskDrawable.setCallback(this);
93+
}
94+
95+
mDrawCircularShadow = a.getBoolean(R.styleable.BezelImageView_biv_drawCircularShadow, true);
96+
97+
mSelectorColor = a.getColor(R.styleable.BezelImageView_biv_selectorOnPress, 0);
98+
99+
a.recycle();
100+
101+
// Other initialization
102+
mBlackPaint = new Paint();
103+
mBlackPaint.setColor(0xff000000);
104+
105+
mMaskedPaint = new Paint();
106+
mMaskedPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
107+
108+
// Always want a cache allocated.
109+
mCacheBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
110+
111+
// Create a desaturate color filter for pressed state.
112+
ColorMatrix cm = new ColorMatrix();
113+
cm.setSaturation(0);
114+
mDesaturateColorFilter = new ColorMatrixColorFilter(cm);
115+
116+
//create a selectorFilter if we already have a color
117+
if (mSelectorColor != 0) {
118+
this.mSelectorFilter = new PorterDuffColorFilter(Color.argb(mSelectorAlpha, Color.red(mSelectorColor), Color.green(mSelectorColor), Color.blue(mSelectorColor)), PorterDuff.Mode.SRC_ATOP);
119+
}
120+
}
121+
122+
@Override
123+
protected void onSizeChanged(int w, int h, int old_w, int old_h) {
124+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
125+
if (mDrawCircularShadow) {
126+
setOutlineProvider(new CustomOutline(w, h));
127+
}
128+
}
129+
}
130+
131+
@TargetApi(21)
132+
private class CustomOutline extends ViewOutlineProvider {
133+
134+
int width;
135+
int height;
136+
137+
CustomOutline(int width, int height) {
138+
this.width = width;
139+
this.height = height;
140+
}
141+
142+
@Override
143+
public void getOutline(View view, Outline outline) {
144+
outline.setOval(0, 0, width, height);
145+
}
146+
}
147+
148+
@Override
149+
protected boolean setFrame(int l, int t, int r, int b) {
150+
final boolean changed = super.setFrame(l, t, r, b);
151+
mBounds = new Rect(0, 0, r - l, b - t);
152+
mBoundsF = new RectF(mBounds);
153+
154+
if (mMaskDrawable != null) {
155+
mMaskDrawable.setBounds(mBounds);
156+
}
157+
158+
if (changed) {
159+
mCacheValid = false;
160+
}
161+
162+
return changed;
163+
}
164+
165+
@Override
166+
protected void onDraw(Canvas canvas) {
167+
if (mBounds == null) {
168+
return;
169+
}
170+
171+
int width = mBounds.width();
172+
int height = mBounds.height();
173+
174+
if (width == 0 || height == 0) {
175+
return;
176+
}
177+
178+
if (!mCacheValid || width != mCachedWidth || height != mCachedHeight || isSelected != isPressed) {
179+
// Need to redraw the cache
180+
if (width == mCachedWidth && height == mCachedHeight) {
181+
// Have a correct-sized bitmap cache already allocated. Just erase it.
182+
mCacheBitmap.eraseColor(0);
183+
} else {
184+
// Allocate a new bitmap with the correct dimensions.
185+
mCacheBitmap.recycle();
186+
//noinspection AndroidLintDrawAllocation
187+
mCacheBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
188+
mCachedWidth = width;
189+
mCachedHeight = height;
190+
}
191+
192+
Canvas cacheCanvas = new Canvas(mCacheBitmap);
193+
if (mMaskDrawable != null) {
194+
int sc = cacheCanvas.save();
195+
mMaskDrawable.draw(cacheCanvas);
196+
if (isSelected) {
197+
if (mSelectorFilter != null) {
198+
mMaskedPaint.setColorFilter(mSelectorFilter);
199+
} else {
200+
mMaskedPaint.setColorFilter(mDesaturateColorFilter);
201+
202+
}
203+
} else {
204+
mMaskedPaint.setColorFilter(null);
205+
}
206+
cacheCanvas.saveLayer(mBoundsF, mMaskedPaint,
207+
Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.FULL_COLOR_LAYER_SAVE_FLAG);
208+
super.onDraw(cacheCanvas);
209+
cacheCanvas.restoreToCount(sc);
210+
} else if (isSelected) {
211+
int sc = cacheCanvas.save();
212+
cacheCanvas.drawRect(0, 0, mCachedWidth, mCachedHeight, mBlackPaint);
213+
if (mSelectorFilter != null) {
214+
mMaskedPaint.setColorFilter(mSelectorFilter);
215+
} else {
216+
mMaskedPaint.setColorFilter(mDesaturateColorFilter);
217+
}
218+
cacheCanvas.saveLayer(mBoundsF, mMaskedPaint,
219+
Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.FULL_COLOR_LAYER_SAVE_FLAG);
220+
super.onDraw(cacheCanvas);
221+
cacheCanvas.restoreToCount(sc);
222+
} else {
223+
super.onDraw(cacheCanvas);
224+
}
225+
}
226+
227+
// Draw from cache
228+
canvas.drawBitmap(mCacheBitmap, mBounds.left, mBounds.top, null);
229+
230+
//remember the previous press state
231+
isPressed = isPressed();
232+
}
233+
234+
235+
@Override
236+
public boolean dispatchTouchEvent(MotionEvent event) {
237+
// Check for clickable state and do nothing if disabled
238+
if (!this.isClickable()) {
239+
this.isSelected = false;
240+
return super.onTouchEvent(event);
241+
}
242+
243+
// Set selected state based on Motion Event
244+
switch (event.getAction()) {
245+
case MotionEvent.ACTION_DOWN:
246+
this.isSelected = true;
247+
break;
248+
case MotionEvent.ACTION_UP:
249+
case MotionEvent.ACTION_SCROLL:
250+
case MotionEvent.ACTION_OUTSIDE:
251+
case MotionEvent.ACTION_CANCEL:
252+
this.isSelected = false;
253+
break;
254+
}
255+
256+
// Redraw image and return super type
257+
this.invalidate();
258+
return super.dispatchTouchEvent(event);
259+
}
260+
261+
@Override
262+
protected void drawableStateChanged() {
263+
super.drawableStateChanged();
264+
if (mMaskDrawable != null && mMaskDrawable.isStateful()) {
265+
mMaskDrawable.setState(getDrawableState());
266+
}
267+
}
268+
269+
@Override
270+
public void invalidateDrawable(Drawable who) {
271+
if (who == mMaskDrawable) {
272+
invalidate();
273+
} else {
274+
super.invalidateDrawable(who);
275+
}
276+
}
277+
278+
@Override
279+
protected boolean verifyDrawable(Drawable who) {
280+
return who == mMaskDrawable || super.verifyDrawable(who);
281+
}
282+
283+
284+
/**
285+
* Sets the color of the selector to be draw over the
286+
* CircularImageView. Be sure to provide some opacity.
287+
*
288+
* @param selectorColor The color (including alpha) to set for the selector overlay.
289+
*/
290+
public void setSelectorColor(int selectorColor) {
291+
this.mSelectorColor = selectorColor;
292+
this.mSelectorFilter = new PorterDuffColorFilter(Color.argb(mSelectorAlpha, Color.red(mSelectorColor), Color.green(mSelectorColor), Color.blue(mSelectorColor)), PorterDuff.Mode.SRC_ATOP);
293+
this.invalidate();
294+
}
295+
296+
297+
@Override
298+
public void setImageDrawable(Drawable drawable) {
299+
super.setImageDrawable(drawable);
300+
}
301+
302+
@Override
303+
public void setImageResource(int resId) {
304+
super.setImageResource(resId);
305+
}
306+
307+
@Override
308+
public void setImageBitmap(Bitmap bm) {
309+
super.setImageBitmap(bm);
310+
}
311+
312+
private ColorMatrixColorFilter mTempDesaturateColorFilter;
313+
private ColorFilter mTempSelectorFilter;
314+
315+
public void disableTouchFeedback(boolean disable) {
316+
if (disable) {
317+
mTempDesaturateColorFilter = this.mDesaturateColorFilter;
318+
mTempSelectorFilter = this.mSelectorFilter;
319+
this.mSelectorFilter = null;
320+
this.mDesaturateColorFilter = null;
321+
} else {
322+
if (mTempDesaturateColorFilter != null) {
323+
this.mDesaturateColorFilter = mTempDesaturateColorFilter;
324+
}
325+
if (mTempSelectorFilter != null) {
326+
this.mSelectorFilter = mTempSelectorFilter;
327+
}
328+
}
329+
}
330+
}

headerview/src/main/java/rebus/header/view/HeaderCompactView.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
package rebus.header.view;
2626

27+
import android.annotation.SuppressLint;
2728
import android.content.Context;
2829
import android.graphics.Bitmap;
2930
import android.graphics.Canvas;
@@ -46,10 +47,11 @@
4647
import android.widget.RelativeLayout;
4748
import android.widget.TextView;
4849

50+
@SuppressLint("ViewConstructor")
4951
public class HeaderCompactView extends RelativeLayout {
5052

5153
private ImageView headerBackground;
52-
private AvatarView avatar;
54+
private BezelImageView avatar;
5355
private TextView userName;
5456
private TextView userEmail;
5557
private HeaderInterface.OnHeaderClickListener onHeaderClickListener;
@@ -186,7 +188,7 @@ private LinearLayout headerUserContainer() {
186188
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
187189
LinearLayout.LayoutParams avatarParams = new LinearLayout.LayoutParams(avatarSize, avatarSize);
188190
avatarParams.setMargins(0, 0, marginSize, 0);
189-
avatar = new AvatarView(getContext());
191+
avatar = new BezelImageView(getContext());
190192
avatar.setLayoutParams(avatarParams);
191193
avatar.setScaleType(ImageView.ScaleType.CENTER_CROP);
192194
avatar.setOnClickListener(new OnClickListener() {
@@ -206,7 +208,7 @@ public ImageView background() {
206208
return headerBackground;
207209
}
208210

209-
public AvatarView avatar() {
211+
public BezelImageView avatar() {
210212
return avatar;
211213
}
212214

0 commit comments

Comments
 (0)