diff --git a/library/build.gradle b/library/build.gradle index 65c9b09ee..e7894d855 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -20,7 +20,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:1.0.0' + classpath 'com.android.tools.build:gradle:1.3.0' } } diff --git a/library/src/main/java/com/github/amlcurran/showcaseview/MaterialShowcaseDrawer.java b/library/src/main/java/com/github/amlcurran/showcaseview/MaterialShowcaseDrawer.java new file mode 100644 index 000000000..8b6680113 --- /dev/null +++ b/library/src/main/java/com/github/amlcurran/showcaseview/MaterialShowcaseDrawer.java @@ -0,0 +1,67 @@ +package com.github.amlcurran.showcaseview; + +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; + +public class MaterialShowcaseDrawer implements ShowcaseDrawer { + + private final float radius; + private final Paint basicPaint; + private final Paint eraserPaint; + private int backgroundColor; + + public MaterialShowcaseDrawer(Resources resources) { + this.radius = resources.getDimension(R.dimen.showcase_radius_material); + this.eraserPaint = new Paint(); + this.eraserPaint.setColor(0xFFFFFF); + this.eraserPaint.setAlpha(0); + this.eraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY)); + this.eraserPaint.setAntiAlias(true); + this.basicPaint = new Paint(); + } + + @Override + public void setShowcaseColour(int color) { + // no-op + } + + @Override + public void drawShowcase(Bitmap buffer, float x, float y, float scaleMultiplier) { + Canvas bufferCanvas = new Canvas(buffer); + bufferCanvas.drawCircle(x, y, radius, eraserPaint); + } + + @Override + public int getShowcaseWidth() { + return (int) (radius * 2); + } + + @Override + public int getShowcaseHeight() { + return (int) (radius * 2); + } + + @Override + public float getBlockedRadius() { + return radius; + } + + @Override + public void setBackgroundColour(int backgroundColor) { + this.backgroundColor = backgroundColor; + } + + @Override + public void erase(Bitmap bitmapBuffer) { + bitmapBuffer.eraseColor(backgroundColor); + } + + @Override + public void drawToCanvas(Canvas canvas, Bitmap bitmapBuffer) { + canvas.drawBitmap(bitmapBuffer, 0, 0, basicPaint); + } +} diff --git a/library/src/main/java/com/github/amlcurran/showcaseview/ShowcaseDrawer.java b/library/src/main/java/com/github/amlcurran/showcaseview/ShowcaseDrawer.java index 3cd82aaa4..d7eb2a327 100644 --- a/library/src/main/java/com/github/amlcurran/showcaseview/ShowcaseDrawer.java +++ b/library/src/main/java/com/github/amlcurran/showcaseview/ShowcaseDrawer.java @@ -19,10 +19,7 @@ import android.graphics.Bitmap; import android.graphics.Canvas; -/** - * Created by curraa01 on 13/10/2013. - */ -interface ShowcaseDrawer { +public interface ShowcaseDrawer { void setShowcaseColour(int color); diff --git a/library/src/main/java/com/github/amlcurran/showcaseview/ShowcaseView.java b/library/src/main/java/com/github/amlcurran/showcaseview/ShowcaseView.java index 994251051..438be1784 100644 --- a/library/src/main/java/com/github/amlcurran/showcaseview/ShowcaseView.java +++ b/library/src/main/java/com/github/amlcurran/showcaseview/ShowcaseView.java @@ -50,7 +50,7 @@ public class ShowcaseView extends RelativeLayout private final Button mEndButton; private final TextDrawer textDrawer; - private final ShowcaseDrawer showcaseDrawer; + private ShowcaseDrawer showcaseDrawer; private final ShowcaseAreaCalculator showcaseAreaCalculator; private final AnimationFactory animationFactory; private final ShotStateStore shotStateStore; @@ -75,6 +75,8 @@ public class ShowcaseView extends RelativeLayout private long fadeInMillis; private long fadeOutMillis; private boolean isShowing; + private int backgroundColor; + private int showcaseColor; protected ShowcaseView(Context context, boolean newStyle) { this(context, null, R.styleable.CustomTheme_showcaseViewStyle, newStyle); @@ -392,6 +394,12 @@ public Builder(Activity activity) { this(activity, false); } + /** + * @param useNewStyle should use "new style" showcase (see {@link #withNewStyleShowcase()} + * @deprecated use {@link #withHoloShowcase()}, {@link #withNewStyleShowcase()}, or + * {@link #setShowcaseDrawer(ShowcaseDrawer)} + */ + @Deprecated public Builder(Activity activity, boolean useNewStyle) { this.activity = activity; this.showcaseView = new ShowcaseView(activity, useNewStyle); @@ -408,6 +416,38 @@ public ShowcaseView build() { return showcaseView; } + /** + * Draw a holo-style showcase. This is the default.
+ * Holo showcase example + */ + public Builder withHoloShowcase() { + return setShowcaseDrawer(new StandardShowcaseDrawer(activity.getResources())); + } + + /** + * Draw a new-style showcase.
+ * Holo showcase example + */ + public Builder withNewStyleShowcase() { + return setShowcaseDrawer(new NewShowcaseDrawer(activity.getResources())); + } + + /** + * Draw a material style showcase. + * Material showcase + */ + public Builder withMaterialShowcase() { + return setShowcaseDrawer(new MaterialShowcaseDrawer(activity.getResources())); + } + + /** + * Set a custom showcase drawer which will be responsible for measuring and drawing the showcase + */ + public Builder setShowcaseDrawer(ShowcaseDrawer showcaseDrawer) { + showcaseView.setShowcaseDrawer(showcaseDrawer); + return this; + } + /** * Set the title text shown on the ShowcaseView. */ @@ -506,17 +546,33 @@ public Builder setShowcaseEventListener(OnShowcaseEventListener showcaseEventLis return this; } + /** + * Sets the paint that will draw the text as specified by {@link #setContentText(CharSequence)} + * or {@link #setContentText(int)} + */ public Builder setContentTextPaint(TextPaint textPaint) { showcaseView.setContentTextPaint(textPaint); return this; } + /** + * Sets the paint that will draw the text as specified by {@link #setContentTitle(CharSequence)} + * or {@link #setContentTitle(int)} + */ public Builder setContentTitlePaint(TextPaint textPaint) { showcaseView.setContentTitlePaint(textPaint); return this; } } + private void setShowcaseDrawer(ShowcaseDrawer showcaseDrawer) { + this.showcaseDrawer = showcaseDrawer; + this.showcaseDrawer.setBackgroundColour(backgroundColor); + this.showcaseDrawer.setShowcaseColour(showcaseColor); + hasAlteredText = true; + invalidate(); + } + private void setContentTitlePaint(TextPaint textPaint) { this.textDrawer.setTitlePaint(textPaint); hasAlteredText = true; @@ -595,8 +651,8 @@ public boolean isShowing() { } private void updateStyle(TypedArray styled, boolean invalidate) { - int backgroundColor = styled.getColor(R.styleable.ShowcaseView_sv_backgroundColor, Color.argb(128, 80, 80, 80)); - int showcaseColor = styled.getColor(R.styleable.ShowcaseView_sv_showcaseColor, HOLO_BLUE); + backgroundColor = styled.getColor(R.styleable.ShowcaseView_sv_backgroundColor, Color.argb(128, 80, 80, 80)); + showcaseColor = styled.getColor(R.styleable.ShowcaseView_sv_showcaseColor, HOLO_BLUE); String buttonText = styled.getString(R.styleable.ShowcaseView_sv_buttonText); if (TextUtils.isEmpty(buttonText)) { buttonText = getResources().getString(android.R.string.ok); diff --git a/library/src/main/res/values/dimens.xml b/library/src/main/res/values/dimens.xml index 2906b7241..e6fb5bb64 100644 --- a/library/src/main/res/values/dimens.xml +++ b/library/src/main/res/values/dimens.xml @@ -22,4 +22,5 @@ 94dp 96dp 128dp + 48dip \ No newline at end of file diff --git a/material.png b/material.png new file mode 100644 index 000000000..7a7bb03e4 Binary files /dev/null and b/material.png differ diff --git a/sample/build.gradle b/sample/build.gradle index 9204b3934..617a2aadb 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -20,7 +20,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:1.0.0' + classpath 'com.android.tools.build:gradle:1.3.0' } } @@ -36,9 +36,9 @@ apply plugin: 'com.android.application' dependencies { compile project(':library') //compile 'com.github.amlcurran.showcaseview:library:5.0.0-SNAPSHOT' - compile 'com.android.support:support-v4:21.0.0' + compile 'com.android.support:support-v4:23.0.1' compile 'com.nineoldandroids:library:2.4.0' - compile 'com.android.support:appcompat-v7:21.0.0' + compile 'com.android.support:appcompat-v7:23.0.1' } android { diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index c14aa071d..b5a8539c5 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -40,5 +40,7 @@ + + diff --git a/sample/src/main/java/com/github/amlcurran/showcaseview/sample/CustomShowcaseActivity.java b/sample/src/main/java/com/github/amlcurran/showcaseview/sample/CustomShowcaseActivity.java new file mode 100644 index 000000000..1d7a2683e --- /dev/null +++ b/sample/src/main/java/com/github/amlcurran/showcaseview/sample/CustomShowcaseActivity.java @@ -0,0 +1,102 @@ +package com.github.amlcurran.showcaseview.sample; + +import android.app.Activity; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.RectF; +import android.os.Bundle; + +import com.github.amlcurran.showcaseview.ShowcaseDrawer; +import com.github.amlcurran.showcaseview.ShowcaseView; +import com.github.amlcurran.showcaseview.targets.ViewTarget; + +public class CustomShowcaseActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_custom_showcase); + + new ShowcaseView.Builder(this) + .setTarget(new ViewTarget(R.id.imageView, this)) + .setContentTitle(R.string.custom_text_painting_title) + .setContentText(R.string.custom_text_painting_text) + .setShowcaseDrawer(new CustomShowcaseView(getResources())) + .build(); + } + + private static class CustomShowcaseView implements ShowcaseDrawer { + + private final float width; + private final float height; + private final Paint eraserPaint; + private final Paint basicPaint; + private final int eraseColour; + private final RectF renderRect; + + public CustomShowcaseView(Resources resources) { + width = resources.getDimension(R.dimen.custom_showcase_width); + height = resources.getDimension(R.dimen.custom_showcase_height); + PorterDuffXfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY); + eraserPaint = new Paint(); + eraserPaint.setColor(0xFFFFFF); + eraserPaint.setAlpha(0); + eraserPaint.setXfermode(xfermode); + eraserPaint.setAntiAlias(true); + eraseColour = resources.getColor(R.color.custom_showcase_bg); + basicPaint = new Paint(); + renderRect = new RectF(); + } + + @Override + public void setShowcaseColour(int color) { + eraserPaint.setColor(color); + } + + @Override + public void drawShowcase(Bitmap buffer, float x, float y, float scaleMultiplier) { + Canvas bufferCanvas = new Canvas(buffer); + renderRect.left = x - width / 2f; + renderRect.right = x + width / 2f; + renderRect.top = y - height / 2f; + renderRect.bottom = y + height / 2f; + bufferCanvas.drawRect(renderRect, eraserPaint); + } + + @Override + public int getShowcaseWidth() { + return (int) width; + } + + @Override + public int getShowcaseHeight() { + return (int) height; + } + + @Override + public float getBlockedRadius() { + return width; + } + + @Override + public void setBackgroundColour(int backgroundColor) { + // No-op, remove this from the API? + } + + @Override + public void erase(Bitmap bitmapBuffer) { + bitmapBuffer.eraseColor(eraseColour); + } + + @Override + public void drawToCanvas(Canvas canvas, Bitmap bitmapBuffer) { + canvas.drawBitmap(bitmapBuffer, 0, 0, basicPaint); + } + + } + +} diff --git a/sample/src/main/java/com/github/amlcurran/showcaseview/sample/CustomTextActivity.java b/sample/src/main/java/com/github/amlcurran/showcaseview/sample/CustomTextActivity.java index 4fd84aeb3..aa0a6ef7b 100644 --- a/sample/src/main/java/com/github/amlcurran/showcaseview/sample/CustomTextActivity.java +++ b/sample/src/main/java/com/github/amlcurran/showcaseview/sample/CustomTextActivity.java @@ -27,6 +27,7 @@ protected void onCreate(Bundle savedInstanceState) { title.setTypeface(Typeface.createFromAsset(getAssets(), "RobotoSlab-Regular.ttf")); new ShowcaseView.Builder(this) + .withNewStyleShowcase() .setTarget(new ViewTarget(R.id.imageView, this)) .setContentTitle(R.string.custom_text_painting_title) .setContentText(R.string.custom_text_painting_text) diff --git a/sample/src/main/java/com/github/amlcurran/showcaseview/sample/SampleActivity.java b/sample/src/main/java/com/github/amlcurran/showcaseview/sample/SampleActivity.java index 8eaadbf1c..c955576ea 100644 --- a/sample/src/main/java/com/github/amlcurran/showcaseview/sample/SampleActivity.java +++ b/sample/src/main/java/com/github/amlcurran/showcaseview/sample/SampleActivity.java @@ -69,7 +69,8 @@ public void onCreate(Bundle savedInstanceState) { lps.setMargins(margin, margin, margin, margin); ViewTarget target = new ViewTarget(R.id.buttonBlocked, this); - sv = new ShowcaseView.Builder(this, true) + sv = new ShowcaseView.Builder(this) + .withMaterialShowcase() .setTarget(target) .setContentTitle(R.string.showcase_main_title) .setContentText(R.string.showcase_main_message) @@ -124,22 +125,21 @@ public void onShowcaseViewShow(ShowcaseView showcaseView) { @Override public void onItemClick(AdapterView adapterView, View view, int position, long l) { switch (position) { - case 0: //startActivity(new Intent(this, ActionItemsSampleActivity.class)); break; - case 1: startActivity(new Intent(this, AnimationSampleActivity.class)); break; - case 2: startActivity(new Intent(this, SingleShotActivity.class)); break; - - // Not currently used case 3: startActivity(new Intent(this, CustomTextActivity.class)); + break; + case 4: + startActivity(new Intent(this, CustomShowcaseActivity.class)); + break; } } @@ -149,14 +149,16 @@ private static class HardcodedListAdapter extends ArrayAdapter { R.string.title_action_items, R.string.title_animations, R.string.title_single_shot, - R.string.custom_text //, R.string.title_memory + R.string.custom_text, + R.string.custom_showcase_title//, R.string.title_memory }; private static final int[] SUMMARY_RES_IDS = new int[] { R.string.sum_action_items, R.string.sum_animations, R.string.sum_single_shot, - R.string.custom_text_summary//, R.string.sum_memory + R.string.custom_text_summary, + R.string.custom_showcase_summary//, R.string.sum_memory }; public HardcodedListAdapter(Context context) { diff --git a/sample/src/main/res/layout/activity_custom_showcase.xml b/sample/src/main/res/layout/activity_custom_showcase.xml new file mode 100644 index 000000000..a9e2baaaa --- /dev/null +++ b/sample/src/main/res/layout/activity_custom_showcase.xml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/sample/src/main/res/values/colors.xml b/sample/src/main/res/values/colors.xml index 668ebc18f..708128f8c 100644 --- a/sample/src/main/res/values/colors.xml +++ b/sample/src/main/res/values/colors.xml @@ -16,5 +16,5 @@ --> - + #b9002153 \ No newline at end of file diff --git a/sample/src/main/res/values/dimens.xml b/sample/src/main/res/values/dimens.xml new file mode 100644 index 000000000..b88d34a00 --- /dev/null +++ b/sample/src/main/res/values/dimens.xml @@ -0,0 +1,5 @@ + + + 96dip + 48dip + \ No newline at end of file diff --git a/sample/src/main/res/values/strings.xml b/sample/src/main/res/values/strings.xml index 54611e033..37113ad67 100644 --- a/sample/src/main/res/values/strings.xml +++ b/sample/src/main/res/values/strings.xml @@ -64,5 +64,9 @@ Custom text See how to create custom text drawing Custom text painting + Custom showcase drawing Here\'s an example of custom text painting + A showcase can be drawn in any shape you like + Custom showcase + Implementing your own drawing for a showcase diff --git a/sample/src/main/res/values/styles.xml b/sample/src/main/res/values/styles.xml index fe9006f1d..f86dce6b3 100644 --- a/sample/src/main/res/values/styles.xml +++ b/sample/src/main/res/values/styles.xml @@ -27,11 +27,12 @@ @style/CustomTitle - - + +