Loading...
Searching...
No Matches
FollowMeButton.java
Go to the documentation of this file.
1package com.navigine.view.widgets;
2
3import android.content.Context;
4import android.content.res.ColorStateList;
5import android.graphics.Color;
6import android.graphics.drawable.Drawable;
7import android.graphics.drawable.GradientDrawable;
8import android.graphics.drawable.ShapeDrawable;
9import android.graphics.drawable.shapes.RoundRectShape;
10import android.view.Gravity;
11import android.view.View;
12import android.view.ViewGroup;
13import android.view.animation.AccelerateDecelerateInterpolator;
14import android.widget.FrameLayout;
15import android.widget.ImageView;
16import android.widget.TextView;
17
18import androidx.annotation.NonNull;
19import androidx.annotation.Nullable;
20
21import com.navigine.R;
22import com.navigine.view.DefaultNavigationViewConfig;
23
33public class FollowMeButton extends FrameLayout {
34
36 public interface OnPressedListener {
37 void onPressed(boolean following);
38 }
39
40 private OnPressedListener onPressedListener;
41 private ImageView arrow;
42 private boolean following = false;
43 private FollowMeButtonConfig config;
44
46 public FollowMeButton(@NonNull Context context, OnPressedListener onPressed) {
47 this(context, onPressed, null);
48 }
49
51 public FollowMeButton(@NonNull Context context, OnPressedListener onPressed,
52 @Nullable FollowMeButtonConfig config) {
53 super(context);
54 this.onPressedListener = onPressed;
55 this.config = config;
56 setupUI();
57 }
58
59 private void setupUI() {
60 setBackground(createFollowButtonBackground());
61 setElevation(dpToPx((int) WidgetStyles.SHADOW_ELEVATION));
62 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
63 setOutlineAmbientShadowColor(WidgetStyles.SHADOW_COLOR);
64 setOutlineSpotShadowColor(WidgetStyles.SHADOW_COLOR);
65 }
66 setOnClickListener(v -> followMePressed());
67 setClickable(true);
68 setFocusable(true);
69
70 FollowMeButtonConfig c = config != null ? config : FollowMeButtonConfig.defaultConfig();
71 arrow = new ImageView(getContext());
72 Drawable icon = c.getFollowMeIcon() != null ? c.getFollowMeIcon() : null;
73 if (icon != null) {
74 arrow.setImageDrawable(icon);
75 } else {
76 arrow.setImageResource(R.drawable.navigine_follow_me);
77 }
78 int tintColor = c.getTextColor() != null ? c.getTextColor() : WidgetStyles.BASE_BLACK;
79 arrow.setImageTintList(ColorStateList.valueOf(tintColor));
80
81 FrameLayout.LayoutParams labelLp = new FrameLayout.LayoutParams(
82 ViewGroup.LayoutParams.MATCH_PARENT,
83 ViewGroup.LayoutParams.MATCH_PARENT
84 );
85 addView(arrow, labelLp);
86 arrow.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
87 arrow.setAdjustViewBounds(true);
88 arrow.setPadding(dpToPx(8), dpToPx(8), dpToPx(8), dpToPx(8));
89
90 updateAppearance();
91 }
92
93 private ShapeDrawable createFollowButtonBackground() {
94 FollowMeButtonConfig c = config != null ? config : FollowMeButtonConfig.defaultConfig();
95 int color = c.getButtonBackgroundColor() != null ? c.getButtonBackgroundColor() : WidgetStyles.BUTTON_BACKGROUND_COLOR;
96 float radius = dpToPx((int) WidgetStyles.BORDER_RADIUS);
97 float[] radii = new float[]{radius, radius, radius, radius, radius, radius, radius, radius};
98
99 ShapeDrawable drawable = new ShapeDrawable(new RoundRectShape(radii, null, null));
100 drawable.getPaint().setAntiAlias(true);
101 drawable.getPaint().setColor(color);
102 return drawable;
103 }
104
106 public void applyConfig(@Nullable FollowMeButtonConfig newConfig) {
107 config = newConfig;
108 updateAppearance();
109 }
110
113 this.following = isFollowing;
114 updateAppearance();
115 }
116
118 public boolean isFollowing() {
119 return following;
120 }
121
122 private void updateAppearance() {
123 if (arrow == null) {
124 return;
125 }
126
127 FollowMeButtonConfig c = config != null ? config : FollowMeButtonConfig.defaultConfig();
128 int accentColor = c.getAccentColor() != null ? c.getAccentColor() : WidgetStyles.BASE_BLUE;
129 int textColor = c.getTextColor() != null ? c.getTextColor() : WidgetStyles.BASE_BLACK;
130 int bgColor = c.getButtonBackgroundColor() != null ? c.getButtonBackgroundColor() : WidgetStyles.BUTTON_BACKGROUND_COLOR;
131
132 if (following) {
133 Drawable activeIcon = c.getFollowMeIconActive() != null ? c.getFollowMeIconActive() : null;
134 if (activeIcon != null) {
135 arrow.setImageDrawable(activeIcon);
136 }
137 arrow.setImageTintList(ColorStateList.valueOf(accentColor));
138
139 GradientDrawable borderDrawable = new GradientDrawable();
140 borderDrawable.setShape(GradientDrawable.RECTANGLE);
141 borderDrawable.setCornerRadius(dpToPx((int) WidgetStyles.BORDER_RADIUS));
142 borderDrawable.setColor(WidgetStyles.WHITE_BACKGROUND_COLOR);
143 borderDrawable.setStroke(dpToPx((int) WidgetStyles.ACTIVE_BORDER_WIDTH), WidgetStyles.BORDER_COLOR);
144 setBackground(borderDrawable);
145 } else {
146 Drawable icon = c.getFollowMeIcon() != null ? c.getFollowMeIcon() : null;
147 if (icon != null) {
148 arrow.setImageDrawable(icon);
149 } else {
150 arrow.setImageResource(R.drawable.navigine_follow_me);
151 }
152 arrow.setImageTintList(ColorStateList.valueOf(textColor));
153
154 float radius = dpToPx((int) WidgetStyles.BORDER_RADIUS);
155 ShapeDrawable background = new ShapeDrawable(new RoundRectShape(
156 new float[]{radius, radius, radius, radius, radius, radius, radius, radius},
157 null, null
158 ));
159 background.getPaint().setAntiAlias(true);
160 background.getPaint().setColor(bgColor);
161 setBackground(background);
162 }
163 }
164
165 private void followMePressed() {
166 following = !following;
167 updateAppearance();
168
169 if (onPressedListener != null) {
170 onPressedListener.onPressed(following);
171 }
172 }
173
174 @Override
175 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
176 FollowMeButtonConfig c = config != null ? config : FollowMeButtonConfig.defaultConfig();
177 float widthDp = c.getButtonWidth() > 0 ? c.getButtonWidth() : WidgetStyles.STANDARD_BUTTON_WIDTH;
179 int widthSpec = MeasureSpec.makeMeasureSpec(dpToPx((int) widthDp), MeasureSpec.EXACTLY);
180 int heightSpec = MeasureSpec.makeMeasureSpec(dpToPx((int) heightDp), MeasureSpec.EXACTLY);
181 super.onMeasure(widthSpec, heightSpec);
182 }
183
184 private int dpToPx(int dp) {
185 return (int) (dp * getResources().getDisplayMetrics().density + 0.5f);
186 }
187}