diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c39b002..66db6c5 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -67,6 +67,16 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/assets/json/BasicTools.json b/app/src/main/assets/json/BasicTools.json
index 6ffeb2e..77639f9 100644
--- a/app/src/main/assets/json/BasicTools.json
+++ b/app/src/main/assets/json/BasicTools.json
@@ -36,6 +36,13 @@
"en": "Base Converter"
},
"activity": "com.fatapp.oxygentoolbox.tools.baseconverter.MainActivity"
+ },
+ {
+ "text": {
+ "cn": "\u0055\u006e\u0069\u0063\u006f\u0064\u0065\u0020\u8f6c\u6362",
+ "en": "Unicode Converter"
+ },
+ "activity": "com.fatapp.oxygentoolbox.tools.unicode.MainActivity"
}
]
}
diff --git a/app/src/main/java/com/fatapp/oxygentoolbox/tools/unicode/MainActivity.java b/app/src/main/java/com/fatapp/oxygentoolbox/tools/unicode/MainActivity.java
new file mode 100644
index 0000000..5e1da62
--- /dev/null
+++ b/app/src/main/java/com/fatapp/oxygentoolbox/tools/unicode/MainActivity.java
@@ -0,0 +1,152 @@
+package com.fatapp.oxygentoolbox.tools.unicode;
+
+import android.graphics.drawable.AnimatedVectorDrawable;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+
+import com.fatapp.oxygentoolbox.R;
+import com.fatapp.oxygentoolbox.util.ResourceUtil;
+import com.fatapp.oxygentoolbox.util.tool.BaseActivityNormal;
+import com.google.android.material.dialog.MaterialAlertDialogBuilder;
+import com.google.android.material.snackbar.Snackbar;
+
+import java.util.List;
+
+public class MainActivity extends BaseActivityNormal {
+ private final List BASE_LIST = List.of(ResourceUtil.getString(R.string.tool_unicode_text),
+ ResourceUtil.getString(R.string.tool_unicode_unicode),
+ ResourceUtil.getString(R.string.tool_unicode_ascii));
+
+ private int baseFrom = 0;
+ private int baseTo = 1;
+ private boolean isFromText = true;
+
+ private TextView textViewBaseFrom;
+ private ImageView imageViewSwap;
+ private TextView textViewBaseTo;
+ private EditText editTextFrom;
+ private TextView textViewTo;
+ private ImageView imageViewConvert;
+
+ private void initView() {
+ textViewBaseFrom = findViewById(R.id.text_view_base_from);
+ imageViewSwap = findViewById(R.id.image_view_swap);
+ textViewBaseTo = findViewById(R.id.text_view_base_to);
+ editTextFrom = findViewById(R.id.edit_text_from);
+ textViewTo = findViewById(R.id.text_view_to);
+ imageViewConvert = findViewById(R.id.image_view_convert);
+ }
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ super.loadView(this, R.layout.activity_tool_unicode);
+
+ initView();
+ initChoose();
+ initConverter();
+ }
+
+ private void initChoose() {
+ textViewBaseFrom.setOnClickListener(v -> new MaterialAlertDialogBuilder(this)
+ .setTitle(ResourceUtil.getString(R.string.tool_common_choose))
+ .setItems(isFromText ?
+ List.of(BASE_LIST.get(0)).toArray(String[]::new) :
+ List.of(BASE_LIST.get(1), BASE_LIST.get(2)).toArray(String[]::new),
+ (dialog, which) -> {
+ textViewBaseFrom.setText(isFromText ? BASE_LIST.get(0) : BASE_LIST.get(which + 1));
+ baseFrom = isFromText ? 0 : (which + 1);
+ if (textViewTo.getText().length() > 0) {
+ convert();
+ }
+ })
+ .show());
+ textViewBaseTo.setOnClickListener(v -> new MaterialAlertDialogBuilder(this)
+ .setTitle(ResourceUtil.getString(R.string.tool_common_choose))
+ .setItems(isFromText ?
+ List.of(BASE_LIST.get(1), BASE_LIST.get(2)).toArray(String[]::new):
+ List.of(BASE_LIST.get(0)).toArray(String[]::new),
+ (dialog, which) -> {
+ textViewBaseTo.setText(isFromText ? BASE_LIST.get(which + 1) : BASE_LIST.get(0));
+ baseTo = isFromText ? (which + 1) : 0;
+ if (textViewTo.getText().length() > 0) {
+ convert();
+ }
+ })
+ .show());
+ imageViewSwap.setOnClickListener(v -> {
+ AnimatedVectorDrawable animatedVectorDrawable = (AnimatedVectorDrawable) imageViewSwap.getDrawable();
+ animatedVectorDrawable.start();
+ isFromText = !isFromText;
+ {
+ int temp = baseFrom;
+ baseFrom = baseTo;
+ baseTo = temp;
+ }
+ {
+ String temp = textViewBaseFrom.getText().toString();
+ textViewBaseFrom.setText(textViewBaseTo.getText());
+ textViewBaseTo.setText(temp);
+ }
+ editTextFrom.setText(null);
+ textViewTo.setText(null);
+ });
+ }
+
+ private void initConverter() {
+ editTextFrom.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ imageViewConvert.setEnabled(s.length() != 0);
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+
+ }
+ });
+ textViewTo.setOnFocusChangeListener((view, b) -> ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(editTextFrom.getWindowToken(), 0));
+ imageViewConvert.setEnabled(false);
+ imageViewConvert.setOnClickListener(view -> convert());
+ }
+
+ private void convert() {
+ ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(editTextFrom.getWindowToken(), 0);
+ switch (baseFrom) {
+ case 0 -> {
+ switch (baseTo) {
+ case 1 ->
+ textViewTo.setText(Utils.stringToUnicode(editTextFrom.getText().toString()));
+ case 2 ->
+ textViewTo.setText(Utils.stringToAscii(editTextFrom.getText().toString()));
+ }
+ }
+ case 1 -> {
+ try {
+ textViewTo.setText(Utils.unicodeToString(editTextFrom.getText().toString()));
+ } catch (Exception e) {
+ Snackbar.make(getConstraintLayoutRoot(), ResourceUtil.getString(R.string.tool_unicode_illegal_input), Snackbar.LENGTH_LONG).show();
+ }
+ }
+ case 2 -> {
+ try {
+ textViewTo.setText(Utils.asciiToString(editTextFrom.getText().toString()));
+ } catch (Exception e) {
+ Snackbar.make(getConstraintLayoutRoot(), ResourceUtil.getString(R.string.tool_unicode_illegal_input), Snackbar.LENGTH_LONG).show();
+ }
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/fatapp/oxygentoolbox/tools/unicode/Utils.java b/app/src/main/java/com/fatapp/oxygentoolbox/tools/unicode/Utils.java
new file mode 100644
index 0000000..09724fa
--- /dev/null
+++ b/app/src/main/java/com/fatapp/oxygentoolbox/tools/unicode/Utils.java
@@ -0,0 +1,52 @@
+package com.fatapp.oxygentoolbox.tools.unicode;
+
+import java.util.StringJoiner;
+
+public class Utils {
+ public static String stringToAscii(String value) {
+ StringJoiner stringJoiner = new StringJoiner(";", "", ";");
+ char[] chars = value.toCharArray();
+ for (char aChar : chars) {
+ stringJoiner.add(String.valueOf((int) aChar));
+ }
+ return stringJoiner.toString();
+ }
+
+ public static String asciiToString(String value) throws Exception {
+ if (!value.startsWith("") || !value.endsWith(";")) {
+ throw new Exception();
+ }
+
+ StringBuilder stringBuffer = new StringBuilder();
+ value = value.substring(2);
+ value = value.substring(0, value.length()-1);
+ String[] chars = value.split(";");
+ for (String aChar : chars) {
+ stringBuffer.append((char) Integer.parseInt(aChar));
+ }
+ return stringBuffer.toString();
+ }
+
+ public static String stringToUnicode(String value) {
+ StringJoiner stringJoiner = new StringJoiner("\\u", "\\u", "");
+ char[] chars = value.toCharArray();
+ for (char aChar : chars) {
+ stringJoiner.add(Integer.toHexString(aChar));
+ }
+ return stringJoiner.toString();
+ }
+
+ public static String unicodeToString(String value) throws Exception {
+ if (!value.startsWith("\\u")) {
+ throw new Exception();
+ }
+
+ StringBuilder stringBuffer = new StringBuilder();
+ value = value.substring(2);
+ String[] chars = value.split("\\\\u");
+ for (String aChar : chars) {
+ stringBuffer.append((char) Integer.parseInt(aChar, 16));
+ }
+ return stringBuffer.toString();
+ }
+}
diff --git a/app/src/main/res/drawable/ic_tool_baseconverter_convert.xml b/app/src/main/res/drawable/ic_tool_arrow_down.xml
similarity index 100%
rename from app/src/main/res/drawable/ic_tool_baseconverter_convert.xml
rename to app/src/main/res/drawable/ic_tool_arrow_down.xml
diff --git a/app/src/main/res/layout/activity_tool_baseconverter.xml b/app/src/main/res/layout/activity_tool_baseconverter.xml
index e17cfea..74820d9 100644
--- a/app/src/main/res/layout/activity_tool_baseconverter.xml
+++ b/app/src/main/res/layout/activity_tool_baseconverter.xml
@@ -30,7 +30,7 @@
android:id="@+id/image_view_swap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:contentDescription="Swap"
+ android:contentDescription="@string/tool_common_swap"
android:padding="@dimen/tool_baseconverter_clickable_padding"
android:src="@drawable/animation_swap_horizon" />
@@ -54,7 +54,7 @@
android:autofillHints="text"
android:background="@drawable/background_radius"
android:gravity="start|top"
- android:hint="@string/tool_baseconverter_please_enter_text"
+ android:hint="@string/tool_common_please_enter_text"
android:inputType="text"
android:maxLength="850"
android:paddingHorizontal="@dimen/tool_baseconverter_edit_text_view_padding"
@@ -96,10 +96,10 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
- android:contentDescription="Convert"
+ android:contentDescription="@string/tool_common_convert"
android:focusable="true"
android:foreground="@drawable/foreground_ripple"
- android:src="@drawable/ic_tool_baseconverter_convert"
+ android:src="@drawable/ic_tool_arrow_down"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
diff --git a/app/src/main/res/layout/activity_tool_translation.xml b/app/src/main/res/layout/activity_tool_translation.xml
index b05e1d8..9ea0bde 100644
--- a/app/src/main/res/layout/activity_tool_translation.xml
+++ b/app/src/main/res/layout/activity_tool_translation.xml
@@ -30,7 +30,7 @@
android:id="@+id/image_view_swap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:contentDescription="Swap"
+ android:contentDescription="@string/tool_common_swap"
android:padding="@dimen/tool_translation_clickable_padding"
android:src="@drawable/animation_swap_horizon" />
@@ -54,7 +54,7 @@
android:autofillHints="text"
android:background="@drawable/background_radius"
android:gravity="start|top"
- android:hint="@string/tool_translation_please_enter_text"
+ android:hint="@string/tool_common_please_enter_text"
android:inputType="textMultiLine"
android:maxLength="850"
android:paddingHorizontal="@dimen/tool_translation_edit_text_view_padding"
@@ -96,7 +96,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
- android:contentDescription="Translate"
+ android:contentDescription="@string/tool_common_translation"
android:focusable="true"
android:foreground="@drawable/foreground_ripple"
android:src="@drawable/ic_tool_translation_translate"
diff --git a/app/src/main/res/layout/activity_tool_unicode.xml b/app/src/main/res/layout/activity_tool_unicode.xml
new file mode 100644
index 0000000..808e863
--- /dev/null
+++ b/app/src/main/res/layout/activity_tool_unicode.xml
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fold_layout_button.xml b/app/src/main/res/layout/fold_layout_button.xml
index f47d43f..b74f20e 100644
--- a/app/src/main/res/layout/fold_layout_button.xml
+++ b/app/src/main/res/layout/fold_layout_button.xml
@@ -4,5 +4,6 @@
xmlns:android="http://schemas.android.com/apk/res/android">
\ No newline at end of file
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index 5e69d02..3ecee3c 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -74,13 +74,20 @@
关于
关于 氧工具
+ 请输入内容……
+ 转换
+ 翻译
+ 交换
+ 选择
+
选择语言
- 请输入内容……
翻译失败,请检查网络连接。
选择进制
源进制
目标进制
- 请输入内容……
非法数字
+
+ 文本
+ 非法输入
\ No newline at end of file
diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml
index 5e69d02..3ecee3c 100644
--- a/app/src/main/res/values-zh-rHK/strings.xml
+++ b/app/src/main/res/values-zh-rHK/strings.xml
@@ -74,13 +74,20 @@
关于
关于 氧工具
+ 请输入内容……
+ 转换
+ 翻译
+ 交换
+ 选择
+
选择语言
- 请输入内容……
翻译失败,请检查网络连接。
选择进制
源进制
目标进制
- 请输入内容……
非法数字
+
+ 文本
+ 非法输入
\ No newline at end of file
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index 5e69d02..3ecee3c 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -74,13 +74,20 @@
关于
关于 氧工具
+ 请输入内容……
+ 转换
+ 翻译
+ 交换
+ 选择
+
选择语言
- 请输入内容……
翻译失败,请检查网络连接。
选择进制
源进制
目标进制
- 请输入内容……
非法数字
+
+ 文本
+ 非法输入
\ No newline at end of file
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index 078479b..94eead3 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -2,6 +2,7 @@
10dp
20sp
+ 16sp
288dp
@@ -38,17 +39,24 @@
120dp
100sp
- 16sp
+ @dimen/common_text_size_small
5dp
15dp
30dp
@dimen/common_layout_margin
200dp
- 16sp
+ @dimen/common_text_size_small
5dp
@dimen/common_layout_margin
200dp
15dp
30dp
+
+ @dimen/common_text_size_small
+ 5dp
+ @dimen/common_layout_margin
+ 200dp
+ 15dp
+ 30dp
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 35c1e25..11a0cfe 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -108,12 +108,17 @@
:
+ Please enter text…
+ Convert
+ Translation
+ Swap
+ Choose
+
Choose a language
中文
English
日本
한국인
- Please enter text…
Translation failed, please check network connection.
2 (binary)
@@ -123,6 +128,10 @@
Choose base
From Base
To Base
- Please enter text…
Illegal Number
+
+ ASCII
+ Unicode
+ Text
+ Illegal Input
\ No newline at end of file
diff --git a/app/src/test/java/com/fatapp/oxygentoolbox/tools/unicode/UtilsTest.java b/app/src/test/java/com/fatapp/oxygentoolbox/tools/unicode/UtilsTest.java
new file mode 100644
index 0000000..c9509c3
--- /dev/null
+++ b/app/src/test/java/com/fatapp/oxygentoolbox/tools/unicode/UtilsTest.java
@@ -0,0 +1,27 @@
+package com.fatapp.oxygentoolbox.tools.unicode;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class UtilsTest {
+ @Test
+ public void stringToAsciiTest() {
+ assertEquals(Utils.stringToAscii("安卓"), "安卓");
+ }
+
+ @Test
+ public void asciiToStringTest() throws Exception {
+ assertEquals(Utils.asciiToString("安卓"), "安卓");
+ }
+
+ @Test
+ public void stringToUnicodeTest() {
+ assertEquals(Utils.stringToUnicode("安卓"), "\\u5b89\\u5353");
+ }
+
+ @Test
+ public void unicodeToStringTest() throws Exception {
+ assertEquals(Utils.unicodeToString("\\u5b89\\u5353"), "安卓");
+ }
+}