package com.beardedhen.androidbootstrap; import android.content.Context; import android.content.res.TypedArray; import android.os.Bundle; import android.os.Parcelable; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.Gravity; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.LinearInterpolator; import android.view.animation.RotateAnimation; import android.widget.TextView; import com.beardedhen.androidbootstrap.api.attributes.BootstrapBrand; import com.beardedhen.androidbootstrap.api.defaults.DefaultBootstrapBrand; import com.beardedhen.androidbootstrap.api.view.BootstrapBrandView; import com.beardedhen.androidbootstrap.api.view.BootstrapTextView; import com.beardedhen.androidbootstrap.font.FontAwesome; import com.beardedhen.androidbootstrap.font.IconSet; import com.beardedhen.androidbootstrap.font.MaterialIcons; import com.beardedhen.androidbootstrap.font.Typicon; import java.io.Serializable; /** * This class extends the default Android TextView to supply Bootstrap behaviour. The text color * can be set by changing the BootstrapBrand, and scalable Typeface icons can be interspersed with * regular text, using the BootstrapText spannable. */ public class AwesomeTextView extends TextView implements BootstrapTextView, BootstrapBrandView { private static final String TAG = "com.beardedhen.androidbootstrap.AwesomeTextView"; private BootstrapText bootstrapText; private BootstrapBrand bootstrapBrand; public enum AnimationSpeed { FAST(500, 200), MEDIUM(1000, 500), SLOW(2000, 1000); private final long rotateDuration; private final long flashDuration; AnimationSpeed(long rotateDuration, long flashDuration) { this.rotateDuration = rotateDuration; this.flashDuration = flashDuration; } public long getRotateDuration() { return rotateDuration; } public long getFlashDuration() { return flashDuration; } } public AwesomeTextView(Context context) { super(context); initialise(null); } public AwesomeTextView(Context context, AttributeSet attrs) { super(context, attrs); initialise(attrs); } public AwesomeTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initialise(attrs); } private void initialise(AttributeSet attrs) { TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.AwesomeTextView); String markdownText; try { int typeOrdinal = a.getInt(R.styleable.AwesomeTextView_bootstrapBrand, -1); int faIconOrdinal = a.getInt(R.styleable.AwesomeTextView_fontAwesomeIcon, -1); int typiconOrdinal = a.getInt(R.styleable.AwesomeTextView_typicon, -1); int materialIconOrdinal = a.getInt(R.styleable.AwesomeTextView_materialIcon, -1); boolean clickable = a.getBoolean(R.styleable.AwesomeTextView_android_clickable, true); this.bootstrapBrand = DefaultBootstrapBrand.fromAttributeValue(typeOrdinal); boolean editMode = isInEditMode(); if (typiconOrdinal != -1) { final IconSet typicon = TypefaceProvider.retrieveRegisteredIconSet(Typicon.FONT_PATH, editMode); if (!editMode) { setIcon(typicon.iconCodeForAttrIndex(typiconOrdinal), typicon); } } if (faIconOrdinal != -1) { final IconSet fontAwesome = TypefaceProvider.retrieveRegisteredIconSet(FontAwesome.FONT_PATH, editMode); if (!editMode) { setIcon(fontAwesome.iconCodeForAttrIndex(faIconOrdinal), fontAwesome); } } if (materialIconOrdinal != -1) { final IconSet materialIcons = TypefaceProvider.retrieveRegisteredIconSet(MaterialIcons.FONT_PATH, editMode); if (!editMode) { setIcon(materialIcons.iconCodeForAttrIndex(materialIconOrdinal), materialIcons); } } markdownText = a.getString(R.styleable.AwesomeTextView_bootstrapText); setClickable(clickable); // allows view to reach android:state_pressed int gravity = a.getInt(R.styleable.AwesomeTextView_android_gravity, Gravity.CENTER); setGravity(gravity); } finally { a.recycle(); } if (markdownText != null) { setMarkdownText(markdownText); } updateBootstrapState(); } @Override public Parcelable onSaveInstanceState() { Bundle bundle = new Bundle(); bundle.putParcelable(TAG, super.onSaveInstanceState()); bundle.putSerializable(BootstrapTextView.KEY, bootstrapText); bundle.putSerializable(BootstrapBrand.KEY, bootstrapBrand); return bundle; } @Override public void onRestoreInstanceState(Parcelable state) { if (state instanceof Bundle) { Bundle bundle = (Bundle) state; Serializable text = bundle.getSerializable(BootstrapTextView.KEY); Serializable brand = bundle.getSerializable(BootstrapBrand.KEY); if (brand instanceof BootstrapBrand) { bootstrapBrand = (BootstrapBrand) brand; } if (text instanceof BootstrapText) { bootstrapText = (BootstrapText) text; } state = bundle.getParcelable(TAG); } super.onRestoreInstanceState(state); updateBootstrapState(); } /** * Starts a Flashing Animation on the AwesomeTextView * * @param forever whether the animation should be infinite or play once * @param speed how fast the item should flash */ public void startFlashing(boolean forever, AnimationSpeed speed) { Animation fadeIn = new AlphaAnimation(0, 1); //set up extra variables fadeIn.setDuration(50); fadeIn.setRepeatMode(Animation.REVERSE); //default repeat count is 0, however if user wants, set it up to be infinite fadeIn.setRepeatCount(0); if (forever) { fadeIn.setRepeatCount(Animation.INFINITE); } fadeIn.setStartOffset(speed.getFlashDuration()); startAnimation(fadeIn); } /** * Starts a rotating animation on the AwesomeTextView * * @param clockwise true for clockwise, false for anti clockwise spinning * @param speed how fast the item should rotate */ public void startRotate(boolean clockwise, AnimationSpeed speed) { Animation rotate; //set up the rotation animation if (clockwise) { rotate = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); } else { rotate = new RotateAnimation(360, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); } //set up some extra variables rotate.setRepeatCount(Animation.INFINITE); rotate.setInterpolator(new LinearInterpolator()); rotate.setStartOffset(0); rotate.setRepeatMode(Animation.RESTART); rotate.setDuration(speed.getRotateDuration()); startAnimation(rotate); } /** * Sets the text to display a FontIcon, replacing whatever text is already present. * Used to set the text to display a FontAwesome Icon. * * @param iconSet - An implementation of FontIcon */ public void setIcon(CharSequence iconCode, IconSet iconSet) { setBootstrapText(new BootstrapText.Builder(getContext(), isInEditMode()).addIcon(iconCode, iconSet).build()); } /** * Sets the text to display a FontIcon, replacing whatever text is already present. * Used to set the text to display a FontAwesome Icon. * * @param iconCode the fontawesome icon code e.g. "fa_play" */ public void setFontAwesomeIcon(@FontAwesome.Icon CharSequence iconCode) { setBootstrapText(new BootstrapText.Builder(getContext(), isInEditMode()).addFontAwesomeIcon(iconCode).build()); } /** * Sets the text to display a MaterialIcon, replacing whatever text is already present. * Used to set the text to display a MaterialIcon Icon. * * @param iconCode the fontawesome icon code e.g. "md_share" */ public void setMaterialIcon(@FontAwesome.Icon CharSequence iconCode) { setBootstrapText(new BootstrapText.Builder(getContext(), isInEditMode()).addMaterialIcon(iconCode).build()); } /** * Sets the text to display a FontIcon, replacing whatever text is already present. * Used to set the text to display a Typicon. * * @param iconCode the typicon icon code e.g. "ty_adjust_brightness" */ public void setTypicon(@Typicon.Icon CharSequence iconCode) { setBootstrapText(new BootstrapText.Builder(getContext(), isInEditMode()).addTypicon(iconCode).build()); } @Override public void setMarkdownText(String text) { setBootstrapText(IconResolver.resolveMarkdown(getContext(), text, isInEditMode())); } protected void updateBootstrapState() { if (bootstrapText != null) { setText(bootstrapText); } if (bootstrapBrand != null) { setTextColor(bootstrapBrand.defaultFill(getContext())); } } /* * Getters/Setters */ @Override public void setBootstrapText(BootstrapText bootstrapText) { this.bootstrapText = bootstrapText; updateBootstrapState(); } @Nullable @Override public BootstrapText getBootstrapText() { return bootstrapText; } @Override public void setBootstrapBrand(@NonNull BootstrapBrand bootstrapBrand) { this.bootstrapBrand = bootstrapBrand; updateBootstrapState(); } @NonNull @Override public BootstrapBrand getBootstrapBrand() { return bootstrapBrand; } @Override public void setText(CharSequence text, BufferType type) { super.setText(text, type); bootstrapText = null; } @Override protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { super.onTextChanged(text, start, lengthBefore, lengthAfter); if(!(text!=null && text.length()>0)){ setVisibility(GONE); }else{ setVisibility(VISIBLE); } } }