package com.joanfuentes.hintcaseexample.customBlock;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable;
import android.text.SpannableString;
import android.text.style.TextAppearanceSpan;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.joanfuentes.hintcase.HintCase;
import com.joanfuentes.hintcase.utils.DimenUtils;
import com.joanfuentes.hintcaseassets.hintcontentholders.HintContentHolder;
import com.joanfuentes.hintcaseexample.R;
import java.util.ArrayList;
/**
* Created by joanFuentes on 26/05/16
*
* Example of a custom HintContentHolder which includes an arrow and the necessary methods
* for positioning the arrow based on the position of the hint.
*/
public class CustomHintContentHolder extends HintContentHolder {
public static final int NO_IMAGE = -1;
public static final int BACKGROUND_COLOR_TRANSPARENT = 0x00000000;
private static final int DEFAULT_ARROW_SIZE_IN_PX = 50;
private int borderColor;
private int backgroundColor;
private int borderSize;
private ImageView imageView;
private int imageResourceId;
private CharSequence contentTitle;
private CharSequence contentText;
private int titleStyleId;
private int textStyleId;
private int marginLeft;
private int marginTop;
private int marginRight;
private int marginBottom;
private ArrayList<Integer> alignBlockRules;
private ArrayList<Integer> alignArrowRules;
private int contentTopMargin;
private int contentBottomMargin;
private int contentRightMargin;
private int contentLeftMargin;
private int contentTopPadding;
private int contentBottomPadding;
private int contentRightPadding;
private int contentLeftPadding;
private int gravity;
private float xTranslationImage;
private float yTranslationImage;
private TriangleShapeView arrow;
private HintCase hintCase;
private ViewGroup parent;
private LinearLayout contentLinearLayout;
private int arrowWidth;
private int arrowHeight;
private int shadowSize;
private boolean useBorder;
private TriangleShapeView.Direction arrowDirection;
@Override
public View getView(Context context, final HintCase hintCase, ViewGroup parent) {
this.hintCase = hintCase;
this.parent = parent;
calculateDataToPutTheArroW(hintCase);
setArrow(context);
FrameLayout.LayoutParams frameLayoutParamsBlock = getParentLayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
gravity, marginLeft, marginTop, marginRight, marginBottom);
RelativeLayout fullBlockLayout = new RelativeLayout(context);
fullBlockLayout.setLayoutParams(frameLayoutParamsBlock);
RelativeLayout.LayoutParams relativeLayoutParamsLinear =
new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
for (int rule : alignBlockRules) {
relativeLayoutParamsLinear.addRule(rule);
}
relativeLayoutParamsLinear.topMargin = contentTopMargin;
relativeLayoutParamsLinear.bottomMargin = contentBottomMargin;
relativeLayoutParamsLinear.rightMargin = contentRightMargin;
relativeLayoutParamsLinear.leftMargin = contentLeftMargin;
contentLinearLayout = new LinearLayout(context);
contentLinearLayout.setBackgroundResource(R.drawable.bubble_border_background);
LayerDrawable layerDrawable = (LayerDrawable) contentLinearLayout.getBackground().getCurrent();
GradientDrawable gradientDrawable = (GradientDrawable) layerDrawable.getDrawable(layerDrawable.getNumberOfLayers() - 1);
gradientDrawable.setColor(backgroundColor);
if (useBorder) {
gradientDrawable.setStroke(borderSize, borderColor);
}
contentLinearLayout.setLayoutParams(relativeLayoutParamsLinear);
contentLinearLayout.setGravity(Gravity.CENTER);
int padding = borderSize + shadowSize;
contentLinearLayout.setPadding(padding + contentLeftPadding,
padding + contentTopPadding,
padding + contentRightPadding,
padding + contentBottomPadding);
contentLinearLayout.setOrientation(LinearLayout.VERTICAL);
if (contentTitle != null) {
contentLinearLayout.addView(getTextViewTitle(context));
}
if (existImage()) {
contentLinearLayout.addView(getImage(context, imageView, imageResourceId));
}
if (contentText != null) {
contentLinearLayout.addView(getTextViewDescription(context));
}
fullBlockLayout.addView(contentLinearLayout);
fullBlockLayout.addView(arrow);
return fullBlockLayout;
}
@Override
public void onLayout() {
calculateArrowTranslation();
arrow.setTranslationX(xTranslationImage);
arrow.setTranslationY(yTranslationImage);
if (hintCase.getBlockInfoPosition() == HintCase.HINT_BLOCK_POSITION_RIGHT
|| hintCase.getBlockInfoPosition() == HintCase.HINT_BLOCK_POSITION_LEFT) {
if (arrow.getBottom() >= contentLinearLayout.getBottom()) {
float translationY = arrow.getY() + (arrow.getHeight()/2) - contentLinearLayout.getY() - (contentLinearLayout.getHeight()/2);
contentLinearLayout.setTranslationY(translationY);
}
}
}
private void setArrow(Context context) {
RelativeLayout.LayoutParams relativeLayoutParamsArrow =
new RelativeLayout.LayoutParams(arrowWidth, arrowHeight);
for (int rule : alignArrowRules) {
relativeLayoutParamsArrow.addRule(rule);
}
arrow = new TriangleShapeView(context);
arrow.setBackgroundColor(backgroundColor);
if (useBorder) {
arrow.setBorder(borderSize, borderColor);
}
arrow.setDirection(arrowDirection);
arrow.setShadowSize(shadowSize);
arrow.setLayoutParams(relativeLayoutParamsArrow);
}
private void calculateArrowTranslation() {
int textPosition = hintCase.getBlockInfoPosition();
switch (textPosition) {
case HintCase.HINT_BLOCK_POSITION_TOP:
xTranslationImage = hintCase.getShape().getCenterX() - parent.getWidth()/2;
yTranslationImage = 0;
break;
case HintCase.HINT_BLOCK_POSITION_BOTTOM:
xTranslationImage = hintCase.getShape().getCenterX() - parent.getWidth()/2;
yTranslationImage = 0;
break;
case HintCase.HINT_BLOCK_POSITION_RIGHT:
xTranslationImage = 0;
yTranslationImage = hintCase.getShape().getCenterY()
- parent.getHeight()/2
- DimenUtils.getStatusBarHeight(hintCase.getView().getContext());
break;
case HintCase.HINT_BLOCK_POSITION_LEFT:
xTranslationImage = 0;
yTranslationImage = hintCase.getShape().getCenterY()
- (parent.getHeight()/2)
- DimenUtils.getStatusBarHeight(hintCase.getView().getContext());
break;
default:
xTranslationImage = 0;
yTranslationImage = 0;
}
}
private void calculateDataToPutTheArroW(HintCase hintCase) {
int textPosition = hintCase.getBlockInfoPosition();
alignArrowRules = new ArrayList<>();
alignBlockRules = new ArrayList<>();
switch (textPosition) {
case HintCase.HINT_BLOCK_POSITION_TOP:
alignBlockRules.add(RelativeLayout.ALIGN_PARENT_BOTTOM);
alignArrowRules.add(RelativeLayout.CENTER_HORIZONTAL);
alignArrowRules.add(RelativeLayout.ALIGN_PARENT_BOTTOM);
gravity = Gravity.BOTTOM;
contentRightMargin = 0;
contentLeftMargin = 0;
contentTopMargin = 0;
contentBottomMargin = arrowHeight - borderSize - shadowSize;
arrowDirection = TriangleShapeView.Direction.DOWN;
marginBottom = 0;
break;
case HintCase.HINT_BLOCK_POSITION_BOTTOM:
alignBlockRules.add(RelativeLayout.ALIGN_PARENT_TOP);
alignArrowRules.add(RelativeLayout.CENTER_HORIZONTAL);
alignArrowRules.add(RelativeLayout.ALIGN_PARENT_TOP);
gravity = Gravity.TOP;
contentRightMargin = 0;
contentLeftMargin = 0;
contentTopMargin = arrowHeight - borderSize - shadowSize;
contentBottomMargin = 0;
arrowDirection = TriangleShapeView.Direction.UP;
marginTop = 0;
break;
case HintCase.HINT_BLOCK_POSITION_RIGHT:
alignBlockRules.add(RelativeLayout.ALIGN_PARENT_LEFT);
alignArrowRules.add(RelativeLayout.CENTER_VERTICAL);
alignArrowRules.add(RelativeLayout.ALIGN_PARENT_LEFT);
gravity = Gravity.LEFT;
contentRightMargin = 0;
contentLeftMargin = arrowHeight;
contentTopMargin = 0;
contentBottomMargin = 0;
arrowDirection = TriangleShapeView.Direction.LEFT;
marginLeft = 0;
break;
case HintCase.HINT_BLOCK_POSITION_LEFT:
alignBlockRules.add(RelativeLayout.ALIGN_PARENT_RIGHT);
alignArrowRules.add(RelativeLayout.ALIGN_PARENT_RIGHT);
alignArrowRules.add(RelativeLayout.CENTER_VERTICAL);
gravity = Gravity.RIGHT;
contentRightMargin = arrowHeight;
contentLeftMargin = 0;
contentTopMargin = 0;
contentBottomMargin = 0;
arrowDirection = TriangleShapeView.Direction.RIGHT;
marginRight = 0;
break;
default:
alignBlockRules.add(RelativeLayout.CENTER_HORIZONTAL);
alignArrowRules.add(RelativeLayout.CENTER_IN_PARENT);
gravity = Gravity.CENTER;
contentRightMargin = 0;
contentLeftMargin = 0;
contentTopMargin = 0;
contentBottomMargin = 0;
xTranslationImage = 0;
yTranslationImage = 0;
}
}
private ImageView getImage(Context context, ImageView image, int imageResourceId) {
LinearLayout.LayoutParams linearLayoutParamsImage =
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
1.0f);
linearLayoutParamsImage.setMargins(0, 20, 0, 50);
if (image == null) {
image = new ImageView(context);
}
if (imageResourceId != CustomHintContentHolder.NO_IMAGE) {
image.setImageResource(imageResourceId);
}
image.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
image.setAdjustViewBounds(true);
image.setLayoutParams(linearLayoutParamsImage);
return image;
}
private View getTextViewTitle(Context context) {
LinearLayout.LayoutParams linearLayoutParamsTitle =
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
linearLayoutParamsTitle.setMargins(0, 0, 0, 20);
TextView textViewTitle = new TextView(context);
textViewTitle.setLayoutParams(linearLayoutParamsTitle);
textViewTitle.setGravity(Gravity.CENTER_HORIZONTAL);
SpannableString spannableStringTitle= new SpannableString(contentTitle);
TextAppearanceSpan titleTextAppearanceSpan = new TextAppearanceSpan(context, titleStyleId);
spannableStringTitle.setSpan(titleTextAppearanceSpan, 0, spannableStringTitle.length(), 0);
textViewTitle.setText(spannableStringTitle);
return textViewTitle;
}
private View getTextViewDescription(Context context) {
LinearLayout.LayoutParams linearLayoutParamsText =
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
TextView textViewDescription = new TextView(context);
textViewDescription.setLayoutParams(linearLayoutParamsText);
textViewDescription.setGravity(Gravity.CENTER_HORIZONTAL);
SpannableString spannableStringText= new SpannableString(contentText);
TextAppearanceSpan textTextAppearanceSpan = new TextAppearanceSpan(context, textStyleId);
spannableStringText.setSpan(textTextAppearanceSpan, 0, spannableStringText.length(), 0);
textViewDescription.setText(spannableStringText);
return textViewDescription;
}
private boolean existImage() {
return imageView != null ||
imageResourceId != CustomHintContentHolder.NO_IMAGE;
}
public static class Builder {
private CustomHintContentHolder blockInfo;
private Context context;
public Builder(Context context) {
this.context = context;
this.blockInfo = new CustomHintContentHolder();
this.blockInfo.imageResourceId = NO_IMAGE;
this.blockInfo.arrowWidth = DEFAULT_ARROW_SIZE_IN_PX;
this.blockInfo.arrowHeight = DEFAULT_ARROW_SIZE_IN_PX;
this.blockInfo.useBorder = false;
this.blockInfo.shadowSize = context.getResources().getDimensionPixelSize(R.dimen.shadow);
}
public Builder setBorder(int resourceId, int resId) {
blockInfo.useBorder = true;
blockInfo.borderSize = context.getResources().getDimensionPixelSize(resourceId);
blockInfo.borderColor = context.getResources().getColor(resId);
return this;
}
public Builder setBackgroundColorFromResource(int resId) {
blockInfo.backgroundColor = context.getResources().getColor(resId);
return this;
}
public Builder setBackgroundColor(int color) {
blockInfo.backgroundColor = color;
return this;
}
public Builder setImageDrawableId(int resourceId) {
blockInfo.imageResourceId = resourceId;
return this;
}
public Builder setImageView(ImageView imageView) {
blockInfo.imageView = imageView;
return this;
}
public Builder setContentTitle(CharSequence title) {
blockInfo.contentTitle = title;
return this;
}
public Builder setContentTitle(int resId) {
blockInfo.contentTitle = context.getString(resId);
return this;
}
public Builder setTitleStyle(int resId) {
blockInfo.titleStyleId = resId;
return this;
}
public Builder setContentText(CharSequence text) {
blockInfo.contentText = text;
return this;
}
public Builder setContentText(int resId) {
blockInfo.contentText = context.getString(resId);
return this;
}
public Builder setContentStyle(int resId) {
blockInfo.textStyleId = resId;
return this;
}
public Builder setMargin(int left, int top, int right, int bottom) {
blockInfo.marginLeft = left;
blockInfo.marginTop = top;
blockInfo.marginRight = right;
blockInfo.marginBottom = bottom;
return this;
}
public Builder setMargingByResourcesId(int left, int top, int right, int bottom) {
blockInfo.marginLeft = context.getResources().getDimensionPixelSize(left);
blockInfo.marginTop = context.getResources().getDimensionPixelSize(top);
blockInfo.marginRight = context.getResources().getDimensionPixelSize(right);
blockInfo.marginBottom = context.getResources().getDimensionPixelSize(bottom);
return this;
}
public Builder setContentPadding(int left, int top, int right, int bottom) {
blockInfo.contentLeftPadding = left;
blockInfo.contentTopPadding = top;
blockInfo.contentRightPadding = right;
blockInfo.contentBottomPadding = bottom;
return this;
}
public Builder setContentPaddingByResourcesId(int left, int top, int right, int bottom) {
blockInfo.contentLeftPadding = context.getResources().getDimensionPixelSize(left);
blockInfo.contentTopPadding = context.getResources().getDimensionPixelSize(top);
blockInfo.contentRightPadding = context.getResources().getDimensionPixelSize(right);
blockInfo.contentBottomPadding = context.getResources().getDimensionPixelSize(bottom);
return this;
}
public Builder setArrowSize(int widthResId, int heightResId) {
blockInfo.arrowWidth = context.getResources().getDimensionPixelSize(widthResId);
blockInfo.arrowHeight = context.getResources().getDimensionPixelSize(heightResId);
return this;
}
public CustomHintContentHolder build() {
return blockInfo;
}
}
}