diff --git a/.gitignore b/.gitignore
index c2892a188e06ba15c0e0ef3ee3d8eb81f2d42dd9..9580e83deb86ccb377424dfa58c6a7cd13bdb3b3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,12 +2,6 @@
.gradle
.idea
/local.properties
-/.idea/caches
-/.idea/libraries
-/.idea/modules.xml
-/.idea/workspace.xml
-/.idea/navEditor.xml
-/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a42dfb3935392189cacbc58c639fe9a7b3db9d39..6f89b180abcdec5ff2b7180a6c92705314e8b1b7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,7 @@
ohos 第一个版本
- * 实现了原库的全部 api
- * 因为使用了jsUI开发,没有library文件
+ * 实现了原库的大部分 api
+ * 因为api限制无法设置背景颜色,点击关键字背景改变功能没有实现
diff --git a/README.OPENSOURCE b/README.OPENSOURCE
index 477d8dc36454183c7496fac47d6838e420348f10..d793a3fa30c5df678eca0789cd45ca9ca2ee214d 100644
--- a/README.OPENSOURCE
+++ b/README.OPENSOURCE
@@ -11,7 +11,7 @@
"Upstream URL":"https://github.com/wangshaolei/AutoSpannableTextView",
- "Description":"支持一些关键词可以用下划线文本视图单击"
+ "Description":"文字开头设置图片;关键字设置字体颜色,下划线,点击事件"
}
]
\ No newline at end of file
diff --git a/README.md b/README.md
index f0f834711fcc1c96248907f87e74e3811b68d2b0..9aae15f6d856a7036e66332cfcb5167dfb9baec0 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,13 @@
-
+
# AutoSpannableTextView
## 项目介绍
* 项目名称: AutoSpannableTextView
* 所属系列:openharmony的第三方组件适配移植
-* 功能:支持一些关键词可以用下划线文本视图单击
+* 功能:文字开头设置图片;关键字设置字体颜色,下划线,点击事件
* 项目移植状态:主功能完成
-* 调用差异:新库使用js UI框架开发实现,无library,调用请参考demo
+* 调用差异:无
* 开发版本:sdk6,DevEco Studio 2.2 Beta1
* 基线版本:Release v1.0.1
@@ -15,32 +15,82 @@

## 安装教程
-在sdk6,DevEco Studio 2.2 Beta1下项目可直接运行。
- 如无法运行,删除项目.gradle,.idea,build,gradle,build.gradle文件,
- 并依据自己的版本创建新项目,将新项目的对应文件复制到根目录下
+在sdk6,DevEco Studio 2.2 Beta1下项目可直接运行。如无法运行,删除项目.gradle,.idea,build,gradle,build.gradle文件, 并依据自己的版本创建新项目,将新项目的对应文件复制到根目录下
+
+## 使用说明
+
+java UI方式:
+
+1、在布局xml文件中声明
+
+```xml
+
+
+
+```
+
+2、在ability中调用
-#### 使用说明
-1. 在页面中引入组件
-``````
+```java
+ autoLinkStyleTextView.setOnClickCallBack(position -> {
+ if(position==0){
+ ToastUtil.getInstance().showToast(this,"购买须知");
+ }else{
+ ToastUtil.getInstance().showToast(this,"用户条款");
+ }
+ });
```
-
+
+
+
```
-2. 参数使用说明:
-
-**buy_info:** 购买须知文本
-**user_clause:** 用户条款文本
+2、参数说明
-**activity_title:** 活动介绍文本,渲染的方式与activity_type有关
+| 参数 | 说明 |
+| -------------- | ------------------------------------------------- |
+| buy_info | 购买须知文本 |
+| user_clause | 用户条款文本 |
+| activity_type | 样式类型:开头图片和文本样式:img;文本样式:text |
+| activity_title | 图片路径 |
-**activity_type:** 活动介绍类型,可取值img,text;
-activity_type值为text时,activity_title传入的内容必须是字符串,
-activity_type值为img时,activity_title传入的内容必须为图片路径
-#### 测试信息
+## 测试信息
CodeCheck代码测试无异常
diff --git a/entry/build.gradle b/entry/build.gradle
index 90cf65991f2d360749bd804ce22ab43b70970787..881675cac3ddbbbb4422868d06e3ce89b49ea766 100644
--- a/entry/build.gradle
+++ b/entry/build.gradle
@@ -21,6 +21,8 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar', '*.har'])
testImplementation 'junit:junit:4.13'
ohosTestImplementation 'com.huawei.ohos.testkit:runner:1.0.0.100'
+ // 本地依赖
+ implementation project(':library')
}
decc {
supportType = ['html', 'xml']
diff --git a/entry/src/main/config.json b/entry/src/main/config.json
index 69e96b53560b2b4c30bed9d0b613d10494b2f83e..baf95e0cbaffc8a0218e0bab2942703fbaa4c3e9 100644
--- a/entry/src/main/config.json
+++ b/entry/src/main/config.json
@@ -19,7 +19,7 @@
"customizeData": [
{
"name": "hwc-theme",
- "value": "androidhwext:style/Theme.Emui.NoTitleBar",
+ "value": "androidhwext:style/Theme.Emui.Dark.NoActionBar",
"extra": ""
}
]
@@ -44,8 +44,17 @@
],
"name": "com.len.MainAbility",
"icon": "$media:icon",
- "description": "$string:mainability_description",
- "label": "$string:entry_MainAbility",
+ "label": "$string:app_name",
+ "type": "page",
+ "launchType": "standard"
+ },
+ {
+ "name": "com.len.JavaMainAbility",
+ "type": "page",
+ "launchType": "standard"
+ },
+ {
+ "name": "com.len.JsMainAbility",
"type": "page",
"launchType": "standard"
}
diff --git a/entry/src/main/java/com/len/JavaMainAbility.java b/entry/src/main/java/com/len/JavaMainAbility.java
new file mode 100644
index 0000000000000000000000000000000000000000..ec57f9a4054aca4153668cdc0127636f9616c232
--- /dev/null
+++ b/entry/src/main/java/com/len/JavaMainAbility.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.len;
+
+import com.len.library.AutoLinkStyleTextView;
+import ohos.aafwk.ability.Ability;
+import ohos.aafwk.content.Intent;
+import ohos.agp.utils.Color;
+
+/**
+ * MainAbility
+ *
+ * @since 2021-06-28
+ */
+public class JavaMainAbility extends Ability {
+ @Override
+ public void onStart(Intent intent) {
+ getWindow().setStatusBarColor(Color.getIntColor("#2E409F"));
+ super.onStart(intent);
+ setUIContent(ResourceTable.Layout_ability_java_main);
+
+ AutoLinkStyleTextView autoLinkStyleTextView = (AutoLinkStyleTextView)
+ findComponentById(ResourceTable.Id_autoLinkStyleText);
+ autoLinkStyleTextView.setOnClickCallBack(position -> {
+ if (position == 0) {
+ ToastUtil.getInstance().showToast(this,"购买须知");
+ } else {
+ ToastUtil.getInstance().showToast(this,"用户条款");
+ }
+ });
+ }
+}
diff --git a/entry/src/main/java/com/len/JsMainAbility.java b/entry/src/main/java/com/len/JsMainAbility.java
new file mode 100644
index 0000000000000000000000000000000000000000..d404220fe3c47714c81562aaf149f25bd8949c75
--- /dev/null
+++ b/entry/src/main/java/com/len/JsMainAbility.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.len;
+
+import ohos.aafwk.content.Intent;
+import ohos.ace.ability.AceAbility;
+import ohos.agp.utils.Color;
+
+/**
+ * MainAbility
+ *
+ * @since 2021-06-28
+ */
+public class JsMainAbility extends AceAbility {
+ @Override
+ public void onStart(Intent intent) {
+ getWindow().setStatusBarColor(Color.getIntColor("#2E409F"));
+ super.onStart(intent);
+ }
+}
diff --git a/entry/src/main/java/com/len/MainAbility.java b/entry/src/main/java/com/len/MainAbility.java
index ccb88eb8a01e47b533ab0e38ab6ba52ec5230479..827220c6e0a3325a755c92648fea8c9b8336cdd7 100644
--- a/entry/src/main/java/com/len/MainAbility.java
+++ b/entry/src/main/java/com/len/MainAbility.java
@@ -15,23 +15,41 @@
package com.len;
-import ohos.ace.ability.AceAbility;
+import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
+import ohos.aafwk.content.Operation;
+import ohos.agp.utils.Color;
/**
* MainAbility
*
- * @author:username
* @since 2021-06-28
*/
-public class MainAbility extends AceAbility {
+public class MainAbility extends Ability {
@Override
public void onStart(Intent intent) {
+ getWindow().setStatusBarColor(Color.getIntColor("#2E409F"));
super.onStart(intent);
- }
+ setUIContent(ResourceTable.Layout_ability_main);
- @Override
- public void onStop() {
- super.onStop();
+ findComponentById(ResourceTable.Id_btn_main_skip_java).setClickedListener(component -> {
+ Intent mIntent = new Intent();
+ Operation operation = new Intent.OperationBuilder()
+ .withBundleName(getBundleName())
+ .withAbilityName(JavaMainAbility.class)
+ .build();
+ mIntent.setOperation(operation);
+ startAbility(mIntent);
+ });
+
+ findComponentById(ResourceTable.Id_btn_main_skip_js).setClickedListener(component -> {
+ Intent mIntent = new Intent();
+ Operation operation = new Intent.OperationBuilder()
+ .withBundleName(getBundleName())
+ .withAbilityName(JsMainAbility.class)
+ .build();
+ mIntent.setOperation(operation);
+ startAbility(mIntent);
+ });
}
}
diff --git a/entry/src/main/java/com/len/ToastUtil.java b/entry/src/main/java/com/len/ToastUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..b066ec67d52b729dc804847898c941ba6f99f756
--- /dev/null
+++ b/entry/src/main/java/com/len/ToastUtil.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.len;
+
+import ohos.agp.components.Component;
+import ohos.agp.components.LayoutScatter;
+import ohos.agp.components.Text;
+import ohos.agp.window.dialog.ToastDialog;
+import ohos.app.Context;
+
+/**
+ * Toast工具类
+ *
+ * @since 2021-08-09
+ */
+public class ToastUtil {
+ private ToastDialog toastDialog;
+
+ private ToastUtil() {
+ }
+
+ /**
+ * 实例
+ *
+ * @return 实例
+ */
+ public static ToastUtil getInstance() {
+ return ToastUtilInstance.INSTANCE;
+ }
+
+ /**
+ * Toast实例内部类
+ *
+ * @since 2021-07-14
+ */
+ private static class ToastUtilInstance {
+ private static final ToastUtil INSTANCE = new ToastUtil();
+ }
+
+ /**
+ * 显示Toast
+ *
+ * @param context 上下文
+ * @param content 内容信息
+ */
+ public void showToast(Context context, String content) {
+ if (toastDialog != null && toastDialog.isShowing()) {
+ toastDialog.cancel();
+ }
+
+ Component toastLayout = LayoutScatter.getInstance(context)
+ .parse(ResourceTable.Layout_layout_toast, null, false);
+ Text toastText = (Text) toastLayout.findComponentById(ResourceTable.Id_text_msg_toast);
+ toastText.setText(content);
+ toastDialog = new ToastDialog(context);
+ toastDialog.setComponent(toastLayout);
+ toastDialog.setTransparent(true);
+ toastDialog.show();
+ }
+}
diff --git a/entry/src/main/js/default/common/commpont/textView/textView.css b/entry/src/main/js/default/common/commpont/textView/textView.css
index 3aee2750449d03a2e6e7164a5e61f5d3778c4a61..27052a4cc8805a25129461c4779d96d59c44c0ac 100644
--- a/entry/src/main/js/default/common/commpont/textView/textView.css
+++ b/entry/src/main/js/default/common/commpont/textView/textView.css
@@ -22,14 +22,14 @@
display: flex;
align-items: center;
width: 100%;
- padding: 20px 15px;
+ padding: 15px 15px;
background-color: #4050B5;
}
.header-text{
- font-size: 26px;
+ font-size: 20px;
color: #ffffff;
- font-weight: 700;
+ font-weight: 500;
}
.title {
font-size: 18px;
diff --git a/entry/src/main/resources/base/element/string.json b/entry/src/main/resources/base/element/string.json
index 0bae6bd40f7360d5d818998221b199d3ec0f69c0..8a10ba923cd6deb117f1393f3aa375e17b676d5c 100644
--- a/entry/src/main/resources/base/element/string.json
+++ b/entry/src/main/resources/base/element/string.json
@@ -1,8 +1,8 @@
{
"string": [
{
- "name": "entry_MainAbility",
- "value": "entry_MainAbility"
+ "name": "app_name",
+ "value": "AutoSpannableTextView"
},
{
"name": "mainability_description",
diff --git a/entry/src/main/resources/base/graphic/button_bg.xml b/entry/src/main/resources/base/graphic/button_bg.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0a1258488c1cd807f56cf48cc2641c76ea0217dc
--- /dev/null
+++ b/entry/src/main/resources/base/graphic/button_bg.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/entry/src/main/resources/base/graphic/shape_button_normal.xml b/entry/src/main/resources/base/graphic/shape_button_normal.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6481b9f8a5f0f691bf302844c84593389ed739e4
--- /dev/null
+++ b/entry/src/main/resources/base/graphic/shape_button_normal.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/entry/src/main/resources/base/graphic/shape_button_pressed.xml b/entry/src/main/resources/base/graphic/shape_button_pressed.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5c6851afadacb7212b0ce29cdbb225be9336e6a8
--- /dev/null
+++ b/entry/src/main/resources/base/graphic/shape_button_pressed.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/entry/src/main/resources/base/graphic/toast_bg.xml b/entry/src/main/resources/base/graphic/toast_bg.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d127f7350e2120a0281a002b2aaed7b6399ddf02
--- /dev/null
+++ b/entry/src/main/resources/base/graphic/toast_bg.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/entry/src/main/resources/base/layout/ability_java_main.xml b/entry/src/main/resources/base/layout/ability_java_main.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a053b7aee8da21640376bab60bb2e1c79eecf255
--- /dev/null
+++ b/entry/src/main/resources/base/layout/ability_java_main.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/entry/src/main/resources/base/layout/ability_main.xml b/entry/src/main/resources/base/layout/ability_main.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2bfa4999e6afddb5fb8249bfb38baf2359ced053
--- /dev/null
+++ b/entry/src/main/resources/base/layout/ability_main.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/entry/src/main/resources/base/layout/layout_common_titlebar.xml b/entry/src/main/resources/base/layout/layout_common_titlebar.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4e04509a0d833c747a92ec094492f0f437c95f41
--- /dev/null
+++ b/entry/src/main/resources/base/layout/layout_common_titlebar.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/entry/src/main/resources/base/layout/layout_toast.xml b/entry/src/main/resources/base/layout/layout_toast.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e46de2f47959d54a34c9bb31a3f5a6ef749d2602
--- /dev/null
+++ b/entry/src/main/resources/base/layout/layout_toast.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/entry/src/main/resources/base/media/ic_qupai_subject_information.png b/entry/src/main/resources/base/media/ic_qupai_subject_information.png
new file mode 100644
index 0000000000000000000000000000000000000000..9308fe0dfdf9701d771457bbb624304b74dcadf6
Binary files /dev/null and b/entry/src/main/resources/base/media/ic_qupai_subject_information.png differ
diff --git a/library/.gitignore b/library/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..7d5b7a94f4dcf381f03ff21f28f8a2494b58023f
--- /dev/null
+++ b/library/.gitignore
@@ -0,0 +1,2 @@
+/build
+/node_modules
diff --git a/library/build.gradle b/library/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..8fdfc61ff35636b327137cea650e1bae79ea0d99
--- /dev/null
+++ b/library/build.gradle
@@ -0,0 +1,22 @@
+apply plugin: 'com.huawei.ohos.library'
+//For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section1112183053510
+ohos {
+ compileSdkVersion 6
+ defaultConfig {
+ compatibleSdkVersion 6
+ }
+ buildTypes {
+ release {
+ proguardOpt {
+ proguardEnabled false
+ rulesFiles 'proguard-rules.pro'
+ }
+ }
+ }
+
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ testImplementation 'junit:junit:4.13'
+}
diff --git a/library/consumer-rules.pro b/library/consumer-rules.pro
new file mode 100644
index 0000000000000000000000000000000000000000..9dccc613bc71b04b83531f550bdab2fb667ecfc9
--- /dev/null
+++ b/library/consumer-rules.pro
@@ -0,0 +1 @@
+# Add har specific ProGuard rules for consumer here.
\ No newline at end of file
diff --git a/library/proguard-rules.pro b/library/proguard-rules.pro
new file mode 100644
index 0000000000000000000000000000000000000000..f7666e47561d514b2a76d5a7dfbb43ede86da92a
--- /dev/null
+++ b/library/proguard-rules.pro
@@ -0,0 +1 @@
+# config module specific ProGuard rules here.
\ No newline at end of file
diff --git a/library/src/main/config.json b/library/src/main/config.json
new file mode 100644
index 0000000000000000000000000000000000000000..c3d38fd94894a73310513b58c32931fdd77f2792
--- /dev/null
+++ b/library/src/main/config.json
@@ -0,0 +1,23 @@
+{
+ "app": {
+ "bundleName": "com.len",
+ "vendor": "len",
+ "version": {
+ "code": 1000000,
+ "name": "1.0.0"
+ }
+ },
+ "deviceConfig": {
+ },
+ "module": {
+ "package": "com.len.library",
+ "deviceType": [
+ "phone"
+ ],
+ "distro": {
+ "deliveryWithInstall": true,
+ "moduleName": "library",
+ "moduleType": "har"
+ }
+ }
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/len/library/AutoLinkStyleTextView.java b/library/src/main/java/com/len/library/AutoLinkStyleTextView.java
new file mode 100644
index 0000000000000000000000000000000000000000..1a35d26e621efb788d99ab7f0e0eea12ab06d766
--- /dev/null
+++ b/library/src/main/java/com/len/library/AutoLinkStyleTextView.java
@@ -0,0 +1,399 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain an copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.len.library;
+
+import ohos.agp.components.Attr;
+import ohos.agp.components.AttrHelper;
+import ohos.agp.components.AttrSet;
+import ohos.agp.components.Text;
+import ohos.agp.components.element.Element;
+import ohos.agp.text.RichText;
+import ohos.agp.text.RichTextBuilder;
+import ohos.agp.text.TextForm;
+import ohos.agp.utils.Color;
+import ohos.agp.utils.Rect;
+import ohos.agp.utils.TextTool;
+import ohos.app.Context;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * 局部样式的文本
+ *
+ * @ProjectName: AutoSpannableTextView
+ * @ClassName: AutoLinkStyleTextView
+ * @Description:
+ * @Author: au
+ * @CreateDate: 2021/9/23 10:27
+ * @since 2021-09-23
+ */
+public class AutoLinkStyleTextView extends Text {
+ private static final int LASTINDEX = -1;
+
+ private static final int ELEMENTPADDING = 7;
+
+ // 需要样式的文字
+ private String autoLinkStyleTextViewTextValue = "";
+
+ // 需要样式的文字颜色
+ private Color autoLinkStyleTextViewDefaultColor = new Color(Color.getIntColor("#f23218"));
+
+ // 是否需要样式:下划线
+ private boolean autoLinkStyleTextViewHasUnderLine = true;
+
+ // 文字开头加入图片
+ private Element autoLinkStyleTextViewStartImage;
+
+ // 样式类型:开头图片和文本样式:start_image;文本样式:content_text
+ private String autoLinkStyleTextViewType;
+
+ // 点击的上一个索引
+ private int lastIndex = LASTINDEX;
+
+ // 点击事件
+ private ClickCallBack mClickCallBack;
+
+ private float scale = 0;
+
+ /**
+ * AutoLinkStyleTextView
+ *
+ * @param context Context
+ */
+ public AutoLinkStyleTextView(Context context) {
+ this(context, new AttrSet() {
+ @Override
+ public Optional getStyle() {
+ return Optional.empty();
+ }
+
+ @Override
+ public int getLength() {
+ return 0;
+ }
+
+ @Override
+ public Optional getAttr(int i) {
+ return Optional.empty();
+ }
+
+ @Override
+ public Optional getAttr(String s) {
+ return Optional.empty();
+ }
+ });
+ }
+
+ /**
+ * AutoLinkStyleTextView
+ *
+ * @param context Context
+ * @param attrSet AttrSet
+ */
+ public AutoLinkStyleTextView(Context context, AttrSet attrSet) {
+ this(context, attrSet, null);
+ }
+
+ /**
+ * AutoLinkStyleTextView
+ *
+ * @param context Context
+ * @param attrSet AttrSet
+ * @param styleName String
+ */
+ public AutoLinkStyleTextView(Context context, AttrSet attrSet, String styleName) {
+ super(context, attrSet, styleName);
+
+ if (attrSet.getAttr("autoLinkStyleTextViewTextValue").isPresent()) {
+ autoLinkStyleTextViewTextValue = attrSet.getAttr("autoLinkStyleTextViewTextValue")
+ .get().getStringValue();
+ }
+ if (attrSet.getAttr("autoLinkStyleTextViewDefaultColor").isPresent()) {
+ autoLinkStyleTextViewDefaultColor = attrSet.getAttr("autoLinkStyleTextViewDefaultColor")
+ .get().getColorValue();
+ }
+ if (attrSet.getAttr("autoLinkStyleTextViewHasUnderLine").isPresent()) {
+ autoLinkStyleTextViewHasUnderLine = attrSet.getAttr("autoLinkStyleTextViewHasUnderLine")
+ .get().getBoolValue();
+ }
+ if (attrSet.getAttr("autoLinkStyleTextViewStartImage").isPresent()) {
+ autoLinkStyleTextViewStartImage = attrSet.getAttr("autoLinkStyleTextViewStartImage").get().getElement();
+ }
+ if (attrSet.getAttr("autoLinkStyleTextViewType").isPresent()) {
+ autoLinkStyleTextViewType = attrSet.getAttr("autoLinkStyleTextViewType").get().getStringValue();
+ }
+ addStyle();
+ setStartImageText("");
+ }
+
+ /**
+ * 设置点击事件
+ *
+ * @param clickCallBack 回调
+ */
+ public void setOnClickCallBack(ClickCallBack clickCallBack) {
+ this.mClickCallBack = clickCallBack;
+ }
+
+ /**
+ * setStartImageText
+ *
+ * @param text String
+ * */
+ public void setStartImageText(String text) {
+ if ("start_image".equals(autoLinkStyleTextViewType) && autoLinkStyleTextViewStartImage != null) {
+ String content = text;
+ if (TextTool.isNullOrEmpty(content)) {
+ content = getText();
+ }
+ setText(content);
+
+ addDrawTask((component, canvas) -> {
+ if (scale == 0) {
+ int height = getHeight();
+ Rect bounds = autoLinkStyleTextViewStartImage.getBounds();
+ scale = height / (float) bounds.bottom;
+ int right = (int) (bounds.right * scale);
+ autoLinkStyleTextViewStartImage.setBounds(0, 0, right, height);
+ setAroundElementsPadding(AttrHelper.vp2px(ELEMENTPADDING, getContext()));
+ setAroundElements(autoLinkStyleTextViewStartImage, null, null, null);
+ }
+ });
+ }
+ }
+
+ /**
+ * 添加样式
+ */
+ private void addStyle() {
+ if (TextTool.isNullOrEmpty(getText()) || TextTool.isNullOrEmpty(autoLinkStyleTextViewTextValue)) {
+ return;
+ }
+ List spanTextList = getSpanTextList();
+ if (spanTextList == null || spanTextList.size() == 0) {
+ return;
+ }
+ setRichText(spanTextList);
+ }
+
+ private void setRichText(List spanTextList) {
+ RichTextBuilder builder = new RichTextBuilder();
+ for (SpanText spanText : spanTextList) {
+ if (spanText.isContains()) {
+ builder.mergeForm(new TextForm()
+ .setTextSize(getTextSize())
+ .setTextColor(autoLinkStyleTextViewDefaultColor.getValue())
+ .setUnderline(autoLinkStyleTextViewHasUnderLine)
+ .setTextBackgroundColor(spanText.getBackground())
+ ).addText(spanText.getText());
+ } else {
+ builder.mergeForm(new TextForm()
+ .setTextSize(getTextSize())
+ .setTextColor(getTextColor().getValue())
+ .setUnderline(false)
+ .setTextBackgroundColor(Color.TRANSPARENT.getValue())
+ ).addText(spanText.getText());
+ }
+ }
+ RichText richText = builder.build();
+
+ for (int index = 0; index < spanTextList.size(); index++) {
+ SpanText spanText = spanTextList.get(index);
+ int finalI = index;
+ richText.addTouchEventListener((component, touchEvent) -> {
+
+ if (spanText.isContains()) {
+ if (lastIndex != LASTINDEX) {
+ SpanText lastSpanText = spanTextList.get(lastIndex);
+ lastSpanText.setBackground(Color.TRANSPARENT.getValue());
+ spanTextList.set(lastIndex, lastSpanText);
+ }
+ spanText.setBackground(Color.getIntColor("#FCB0CA"));
+ spanTextList.set(finalI, spanText);
+ setRichText(spanTextList);
+ lastIndex = finalI;
+
+ if (mClickCallBack != null) {
+ mClickCallBack.onClick(spanText.getValueIndex());
+ }
+ } else {
+ if (lastIndex != LASTINDEX) {
+ SpanText lastSpanText = spanTextList.get(lastIndex);
+ lastSpanText.setBackground(Color.TRANSPARENT.getValue());
+ spanTextList.set(lastIndex, lastSpanText);
+ lastIndex = finalI;
+ }
+ }
+ return false;
+ }, spanText.getStartIndex(), spanText.getEndIndex());
+ }
+ setRichText(richText);
+ }
+
+ private List getSpanTextList() {
+ String[] values = autoLinkStyleTextViewTextValue.split(",");
+ List list = new ArrayList<>();
+ String textContent = getText();
+
+ // 有样式的text,进行排序,按前后顺序
+ List listValue = new ArrayList<>();
+ for (int index = 0; index < values.length; index++) {
+ String value = values[index];
+ int startIndex = textContent.indexOf(value);
+ int endIndex = startIndex + value.length();
+ if (startIndex == LASTINDEX) {
+ continue;
+ }
+ SpanText spanText = new SpanText(startIndex, endIndex, value, true);
+ spanText.setValueIndex(index);
+ listValue.add(spanText);
+ }
+ listValue.sort(Comparator.comparing(SpanText::getStartIndex));
+
+ int endIndex = 0;
+ for (int index = 0; index < listValue.size(); index++) {
+ SpanText spanValue = listValue.get(index);
+ int startIndex = spanValue.getStartIndex();
+ String value = spanValue.getText();
+ int valueIndex = spanValue.getValueIndex();
+ if (startIndex == 0) {
+ // 有样式文本
+ endIndex = spanValue.getEndIndex();
+ SpanText spanText = new SpanText(startIndex, endIndex, value, true);
+ spanText.setValueIndex(valueIndex);
+ list.add(spanText);
+ } else {
+ // 无样式文本
+ SpanText noStyleText = new SpanText(endIndex, startIndex,
+ textContent.substring(endIndex, startIndex), false);
+ list.add(noStyleText);
+
+ // 有样式文本
+ endIndex = startIndex + value.length();
+ SpanText haveStyleText = new SpanText(startIndex, endIndex, value, true);
+ haveStyleText.setValueIndex(valueIndex);
+ list.add(haveStyleText);
+ }
+
+ if (index == listValue.size() - 1 && endIndex != textContent.length()) {
+ // 无样式文本
+ SpanText noStyleText = new SpanText(endIndex, textContent.length(),
+ textContent.substring(endIndex), false);
+ list.add(noStyleText);
+ }
+ }
+ return list;
+ }
+ /**
+ * SpanText
+ *
+ * @ProjectName: AutoSpannableTextView
+ * @ClassName: SpanText
+ * @Description:
+ * @Author: au
+ * @CreateDate: 2021/9/23 10:27
+ * @since 2021-09-23
+ */
+ private static class SpanText {
+ private int startIndex;
+ private int endIndex;
+ private String text;
+ private boolean isContains;
+ private int valueIndex = LASTINDEX;
+ private int background = Color.TRANSPARENT.getValue();
+
+ SpanText() {
+ super();
+ }
+
+ SpanText(int startIndex, int endIndex, String text, boolean isContains) {
+ this.startIndex = startIndex;
+ this.endIndex = endIndex;
+ this.text = text;
+ this.isContains = isContains;
+ }
+
+ public int getBackground() {
+ return background;
+ }
+
+ public void setBackground(int background) {
+ this.background = background;
+ }
+
+ public int getValueIndex() {
+ return valueIndex;
+ }
+
+ public void setValueIndex(int valueIndex) {
+ this.valueIndex = valueIndex;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public void setText(String text) {
+ this.text = text;
+ }
+
+ public int getStartIndex() {
+ return startIndex;
+ }
+
+ public void setStartIndex(int startIndex) {
+ this.startIndex = startIndex;
+ }
+
+ public int getEndIndex() {
+ return endIndex;
+ }
+
+ public void setEndIndex(int endIndex) {
+ this.endIndex = endIndex;
+ }
+
+ public boolean isContains() {
+ return isContains;
+ }
+
+ public void setContains(boolean contains) {
+ isContains = contains;
+ }
+ }
+ /**
+ * ClickCallBack
+ *
+ * @ProjectName: AutoSpannableTextView
+ * @ClassName: ClickCallBack
+ * @Description:
+ * @Author: au
+ * @CreateDate: 2021/9/23 10:27
+ * @since 2021-09-23
+ */
+ public interface ClickCallBack {
+
+ /**
+ * onClick
+ *
+ * @param position int
+ * */
+ void onClick(int position);
+ }
+}
diff --git a/library/src/main/resources/base/element/string.json b/library/src/main/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..211a936b6a562815c346636393376e8f1a72a08e
--- /dev/null
+++ b/library/src/main/resources/base/element/string.json
@@ -0,0 +1,8 @@
+{
+ "string": [
+ {
+ "name": "library_library",
+ "value": "library_library"
+ }
+ ]
+}
diff --git a/library/src/test/java/com/len/library/ExampleTest.java b/library/src/test/java/com/len/library/ExampleTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..cad62c891dd522010e00bf073b41390a378ca043
--- /dev/null
+++ b/library/src/test/java/com/len/library/ExampleTest.java
@@ -0,0 +1,9 @@
+package com.len.library;
+
+import org.junit.Test;
+
+public class ExampleTest {
+ @Test
+ public void onStart() {
+ }
+}
diff --git a/settings.gradle b/settings.gradle
index 4773db73233a570c2d0c01a22e75321acfbf7a07..d0c7ee8440156d4a9324ac5357770747425fef57 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1 +1 @@
-include ':entry'
+include ':entry', ':library'