diff --git a/app/build.gradle b/app/build.gradle
index bf31fe2..1df021a 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,35 +1,34 @@
-buildscript {
- repositories {
- mavenCentral()
- }
- dependencies {
- classpath 'com.android.tools.build:gradle:0.7.+'
- }
-}
+
apply plugin: 'android'
+apply plugin: 'kotlin-android-extensions'
+apply plugin: 'kotlin-android'
repositories {
mavenCentral()
}
android {
- compileSdkVersion 19
- buildToolsVersion "19.0.0"
+ compileSdkVersion 29
+ buildToolsVersion "29.0.2"
+
+ lintOptions {
+ abortOnError false
+ }
defaultConfig {
minSdkVersion 17
- targetSdkVersion 19
+ targetSdkVersion 29
versionCode 1
versionName "1.0"
}
buildTypes {
release {
- runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
dependencies {
- compile 'com.android.support:support-v4:13.0.0'
+ compile 'com.android.support:support-v4:27.0.0'
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
diff --git a/app/src/main/java/com/flavienlaurent/spanimated/CornerMarkSpan.java b/app/src/main/java/com/flavienlaurent/spanimated/CornerMarkSpan.java
new file mode 100644
index 0000000..7078f8f
--- /dev/null
+++ b/app/src/main/java/com/flavienlaurent/spanimated/CornerMarkSpan.java
@@ -0,0 +1,89 @@
+package com.flavienlaurent.spanimated;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.text.TextPaint;
+import android.text.TextUtils;
+import android.text.style.ReplacementSpan;
+
+/**
+ */
+public class CornerMarkSpan extends ReplacementSpan {
+
+ private final int cornerHeight;
+ private final int cornerWidth;
+ private TextPaint mCornerPaint;
+ private Paint mTextPaint;
+ private int mWidth;
+ private String text = "";
+
+ private Drawable cornerDrawable;
+ private Rect mCornerBound;
+ private Context mContext;
+
+ public CornerMarkSpan(Context context, Paint textPaint) {
+ mContext = context;
+ mTextPaint = textPaint;
+
+ mCornerPaint = new TextPaint();
+ mCornerPaint.setTextAlign(Paint.Align.CENTER);
+ mCornerPaint.setStyle(Paint.Style.FILL);
+ mCornerPaint.setColor(Color.WHITE);
+ mCornerPaint.setTextSize(mTextPaint.getTextSize() * 0.5f);
+ mCornerPaint.setAntiAlias(true);
+
+ cornerDrawable = context.getResources().getDrawable(R.drawable.corner_back_two_digital);
+
+ cornerHeight = dp2px(context, 15);
+ cornerWidth = dp2px(context, 15);
+
+ mCornerBound = new Rect(0, 0, cornerWidth, cornerHeight);
+ cornerDrawable.setBounds(mCornerBound);
+ }
+
+ /**
+ * dp转px
+ */
+ public static int dp2px(Context context, float dp) {
+ return (int) (dp * context.getResources().getDisplayMetrics().density + 0.5f);
+ }
+
+
+ @Override
+ public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
+ //return text with relative to the Paint
+ mWidth = (int) paint.measureText(text, start, end);
+ if (text == null) {
+ text = "";
+ }
+ this.text = text.toString();
+ return mWidth;
+ }
+
+ @Override
+ public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
+ //draw the frame with custom Paint
+// float halfHeight = (bottom - top) / 2f;
+// canvas.drawCircle(x, top + halfHeight, halfHeight, mPaint);
+ if (!TextUtils.isEmpty(this.text)) {
+ canvas.drawText(text, start, end, x, y, mTextPaint);
+ }
+
+ canvas.save();
+ canvas.translate(x, top - cornerHeight + 3);
+ cornerDrawable.draw(canvas);
+ canvas.restore();
+
+ canvas.save();
+ canvas.translate(cornerWidth / 2f - 2, -cornerHeight - dp2px(mContext, 4));
+ canvas.drawText("12", 0, 2, x, y, mCornerPaint);
+ canvas.restore();
+
+
+// canvas.drawRect(x, top, x + mWidth, bottom, mPaint);
+ }
+}
diff --git a/app/src/main/java/com/flavienlaurent/spanimated/ListNumberSpan.kt b/app/src/main/java/com/flavienlaurent/spanimated/ListNumberSpan.kt
new file mode 100644
index 0000000..2013494
--- /dev/null
+++ b/app/src/main/java/com/flavienlaurent/spanimated/ListNumberSpan.kt
@@ -0,0 +1,90 @@
+package com.flavienlaurent.spanimated
+
+import android.content.Context
+import android.graphics.*
+import android.graphics.Paint.FontMetricsInt
+import android.os.Build
+import android.support.annotation.RequiresApi
+import android.text.TextPaint
+import android.text.style.ReplacementSpan
+import com.flavienlaurent.spanimated.utils.SystemUtils
+
+@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
+class ListNumberSpan(var isGrayStatus: Boolean, var number:String = "",
+ var context: Context) : ReplacementSpan() {
+
+ private val COLOR_SENTENCE_HIGH_LIGHT = Color.parseColor("#66F5FF9A")
+ private val UNSELECT_SENTENCE_BACKGROUND_COLOR = Color.parseColor("#08000000")
+
+ private val backGroundColor: Int = Color.parseColor("#262626")
+ private val backGroundGrayColor: Int = Color.parseColor("#A7A7A7")
+ private val textColor: Int = Color.WHITE
+
+ /**
+ * 圆角矩形 和 数字 底部重叠后,将圆角矩形往Y轴的偏移量
+ */
+ private val numberBaseLineYDelta = SystemUtils.dp2px(context, 3f)
+ private var mNumberWidth = 0
+
+ private val numberPaint: Paint = TextPaint()
+ private val mRectBackgroundPaint: Paint = Paint()
+ private val mRoundRectBackgroundPaint: Paint = Paint()
+
+
+ private val mRoundRectF = RectF()
+ private val roundRectRadius: Float = SystemUtils.dp2px(context, 6f).toFloat()
+
+ /**
+ * 排除数字后的宽度
+ */
+ private val roundRectBackgroundWidth = SystemUtils.dp2px(context, 12f)
+ private val roundRectBackgroundHeight = SystemUtils.dp2px(context, 12f)
+
+ init {
+ initPaint()
+ }
+
+
+ private fun initPaint() {
+ mRectBackgroundPaint.color = if (isGrayStatus) UNSELECT_SENTENCE_BACKGROUND_COLOR else COLOR_SENTENCE_HIGH_LIGHT
+ mRectBackgroundPaint.style = Paint.Style.FILL
+
+ mRoundRectBackgroundPaint.color = if(isGrayStatus) backGroundGrayColor else backGroundColor
+ mRoundRectBackgroundPaint.isAntiAlias = true
+
+ numberPaint.color = textColor
+ numberPaint.isAntiAlias = true
+ numberPaint.textSize = SystemUtils.sp2px(context, 9f).toFloat()
+ numberPaint.textAlign = Paint.Align.CENTER
+ }
+
+ override fun getSize(paint: Paint, text: CharSequence, start: Int, end: Int, fm: FontMetricsInt?): Int { //return text with relative to the Paint
+ mNumberWidth = numberPaint.measureText(text, start, end).toInt()
+ mNumberWidth += roundRectBackgroundWidth
+
+ return mNumberWidth
+ }
+
+ override fun draw(canvas: Canvas, text: CharSequence, start: Int, end: Int, x: Float, top: Int, y: Int, bottom: Int, paint: Paint) {
+ canvas.drawRect(x, top.toFloat(), x + mNumberWidth, bottom.toFloat(), mRectBackgroundPaint)
+ val deltaY = (y - top - roundRectBackgroundHeight + numberBaseLineYDelta).toFloat()
+
+ canvas.save()
+ canvas.translate(0f, (-numberBaseLineYDelta).toFloat())
+
+ canvas.save()
+ canvas.translate(0f, deltaY)
+ mRoundRectF.set(x, top.toFloat(), x + mNumberWidth, top.toFloat() + roundRectBackgroundHeight)
+ canvas.drawRoundRect(mRoundRectF, roundRectRadius, roundRectRadius, mRoundRectBackgroundPaint)
+ canvas.restore()
+
+ canvas.save()
+ canvas.translate(mNumberWidth / 2f ,0f )
+ canvas.drawText(number, 0, number.length, x, y.toFloat(), numberPaint)
+ canvas.restore()
+
+ canvas.restore()
+
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/flavienlaurent/spanimated/MainActivity.java b/app/src/main/java/com/flavienlaurent/spanimated/MainActivity.java
index 2b66fe9..8bcaab2 100644
--- a/app/src/main/java/com/flavienlaurent/spanimated/MainActivity.java
+++ b/app/src/main/java/com/flavienlaurent/spanimated/MainActivity.java
@@ -11,9 +11,12 @@
import android.graphics.Color;
import android.graphics.EmbossMaskFilter;
import android.graphics.Typeface;
+import android.os.Build;
import android.os.Bundle;
+import android.support.annotation.RequiresApi;
import android.text.Layout;
import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.AbsoluteSizeSpan;
import android.text.style.AlignmentSpan;
@@ -43,6 +46,8 @@
import android.widget.Spinner;
import android.widget.TextView;
+import org.jetbrains.annotations.NotNull;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@@ -58,6 +63,8 @@ public class MainActivity extends Activity {
private Button mBtnDraw1;
private Button mBtnDraw2;
private Button mBtnDraw3;
+ private Button mBtnDrawListNum;
+ private Button mBtnDrawCornMark;
private Button mBtnAnimateTypeWriter;
private Button mBtnViewPager;
private Button mBtnAnimateAb1;
@@ -87,6 +94,8 @@ protected void onCreate(Bundle savedInstanceState) {
mBtnDraw1 = (Button) findViewById(R.id.btn_draw1);
mBtnDraw2 = (Button) findViewById(R.id.btn_draw2);
mBtnDraw3 = (Button) findViewById(R.id.btn_draw3);
+ mBtnDrawListNum = (Button) findViewById(R.id.mBtnDrawListNum);
+ mBtnDrawCornMark = (Button) findViewById(R.id.btn_corner_mark);
mBtnAnimateTypeWriter = (Button) findViewById(R.id.btn_animate_typewriter);
mBtnReset = (Button) findViewById(R.id.btn_reset);
mBtnViewPager = (Button) findViewById(R.id.btn_viewpager);
@@ -121,6 +130,21 @@ public void onClick(View v) {
}
});
+ mBtnDrawListNum.setOnClickListener(new View.OnClickListener() {
+ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
+ @Override
+ public void onClick(View v) {
+ reset();
+ drawingListNumberSpan();
+ }
+ });
+ mBtnDrawCornMark.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ reset();
+ drawingCornerMarkSpan();
+ }
+ });
mBtnDraw2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -364,6 +388,30 @@ private void drawingSpan1() {
mText.setText(mBaconIpsumSpannableString);
}
+ private void drawingCornerMarkSpan() {
+ CornerMarkSpan cornerMarkSpan = new CornerMarkSpan(this, mText.getPaint());
+ mSpans.add(cornerMarkSpan);
+
+ WordPosition wordPosition = getWordPosition(mBaconIpsum);
+ mBaconIpsumSpannableString.setSpan(cornerMarkSpan, wordPosition.start, wordPosition.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ //refresh
+ mText.setText(mBaconIpsumSpannableString);
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
+ private void drawingListNumberSpan() {
+ String listNumber = "1234567890";
+ Object spannable = new ListNumberSpan(false,listNumber, this);
+ mSpans.add(spannable);
+
+ WordPosition wordPosition = getWordPosition(mBaconIpsum);
+ SpannableStringBuilder cacheString = new SpannableStringBuilder(mBaconIpsumSpannableString);
+ cacheString.insert(wordPosition.start, listNumber);
+ cacheString.setSpan(spannable, wordPosition.start, wordPosition.start + listNumber.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ //refresh
+ mText.setText(cacheString);
+ }
+
private void animateTypeWriter() {
TypeWriterSpanGroup spanGroup = buildTypeWriterSpanGroup(0, mBaconIpsum.length() - 1);
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(spanGroup, TYPE_WRITER_GROUP_ALPHA_PROPERTY, 0.0f, 1.0f);
diff --git a/app/src/main/java/com/flavienlaurent/spanimated/utils/SystemUtils.kt b/app/src/main/java/com/flavienlaurent/spanimated/utils/SystemUtils.kt
new file mode 100644
index 0000000..e72b345
--- /dev/null
+++ b/app/src/main/java/com/flavienlaurent/spanimated/utils/SystemUtils.kt
@@ -0,0 +1,25 @@
+package com.flavienlaurent.spanimated.utils
+
+import android.content.Context
+
+object SystemUtils {
+
+ /**
+ * 将dip或dp值转换为px值,保证尺寸大小不变
+ */
+ fun dp2px(context: Context, dipValue: Float): Int {
+ val scale = context.resources.displayMetrics.density
+ return (dipValue * scale + 0.5f).toInt()
+ }
+
+
+ /**
+ * 将sp值转换为px值,保证文字大小不变
+ */
+ fun sp2px(context: Context, spValue: Float): Int {
+ val fontScale = context.resources.displayMetrics.scaledDensity
+ return (spValue * fontScale + 0.5f).toInt()
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable-mdpi/corner_drawbale.9.png b/app/src/main/res/drawable-mdpi/corner_drawbale.9.png
new file mode 100644
index 0000000..9818625
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/corner_drawbale.9.png differ
diff --git a/app/src/main/res/drawable-xhdpi/corner_back_one_digital.png b/app/src/main/res/drawable-xhdpi/corner_back_one_digital.png
new file mode 100644
index 0000000..1b3ed08
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/corner_back_one_digital.png differ
diff --git a/app/src/main/res/drawable-xhdpi/corner_back_three_digital.png b/app/src/main/res/drawable-xhdpi/corner_back_three_digital.png
new file mode 100644
index 0000000..da5f172
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/corner_back_three_digital.png differ
diff --git a/app/src/main/res/drawable-xhdpi/corner_back_two_digital.png b/app/src/main/res/drawable-xhdpi/corner_back_two_digital.png
new file mode 100644
index 0000000..a171b3b
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/corner_back_two_digital.png differ
diff --git a/app/src/main/res/drawable-xhdpi/default_corner_back_one_digital.png b/app/src/main/res/drawable-xhdpi/default_corner_back_one_digital.png
new file mode 100644
index 0000000..0d147e9
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/default_corner_back_one_digital.png differ
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 410960a..a979a08 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -17,7 +17,8 @@
android:padding="18dp"
android:text="@string/bacon_ipsum"
android:textColor="@color/text_color"
- android:textSize="16sp"/>
+ android:textSize="18sp"
+ android:lineSpacingExtra="6dp" />
+
+
+
+