Added unicode tool.

This commit is contained in:
2023-07-25 00:31:22 +08:00
parent 02eb4aa1ae
commit 93e49c3719
15 changed files with 412 additions and 17 deletions

View File

@@ -67,6 +67,16 @@
<intent-filter>
<action android:name="oxygentoolbox.baseconverter" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".tools.unicode.MainActivity"
android:exported="false"
android:theme="@style/Theme.OxygenToolbox.Default">
<intent-filter>
<action android:name="oxygentoolbox.unicode" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

View File

@@ -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"
}
]
}

View File

@@ -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<String> 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();
}
}
}
}
}

View File

@@ -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();
}
}

View File

@@ -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"

View File

@@ -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"

View File

@@ -0,0 +1,108 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".tools.unicode.MainActivity">
<LinearLayout
android:id="@+id/linear_layout_base"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/tool_unicode_layout_margin"
android:background="@drawable/background_radius"
android:gravity="center"
android:orientation="horizontal"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/text_view_base_from"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="@string/tool_unicode_text"
android:textColor="?attr/app_theme"
android:textSize="@dimen/tool_unicode_text_size" />
<ImageView
android:id="@+id/image_view_swap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/tool_common_swap"
android:padding="@dimen/tool_unicode_clickable_padding"
android:src="@drawable/animation_swap_horizon" />
<TextView
android:id="@+id/text_view_base_to"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="@string/tool_unicode_unicode"
android:textColor="?attr/app_theme"
android:textSize="@dimen/tool_unicode_text_size" />
</LinearLayout>
<EditText
android:id="@+id/edit_text_from"
android:layout_width="match_parent"
android:layout_height="@dimen/tool_unicode_edit_text_view_height"
android:layout_margin="@dimen/tool_unicode_layout_margin"
android:autofillHints="text"
android:background="@drawable/background_radius"
android:gravity="start|top"
android:hint="@string/tool_common_please_enter_text"
android:inputType="text"
android:maxLength="850"
android:paddingHorizontal="@dimen/tool_unicode_edit_text_view_padding"
android:paddingTop="@dimen/tool_unicode_edit_text_view_padding"
android:paddingBottom="@dimen/tool_unicode_edit_text_view_padding_plus"
android:textColor="?attr/app_text_theme"
android:textSize="@dimen/tool_unicode_text_size"
app:layout_constraintTop_toBottomOf="@id/linear_layout_base" />
<TextView
android:id="@+id/text_view_to"
android:layout_width="match_parent"
android:layout_height="@dimen/tool_unicode_edit_text_view_height"
android:layout_margin="@dimen/tool_unicode_layout_margin"
android:autofillHints="text"
android:background="@drawable/background_radius"
android:gravity="start|top"
android:paddingHorizontal="@dimen/tool_unicode_edit_text_view_padding"
android:paddingTop="@dimen/tool_unicode_edit_text_view_padding_plus"
android:paddingBottom="@dimen/tool_unicode_edit_text_view_padding"
android:textColor="?attr/app_text_theme"
android:textIsSelectable="true"
android:textSize="@dimen/tool_unicode_text_size"
app:layout_constraintTop_toBottomOf="@id/edit_text_from" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/background_round"
android:padding="@dimen/tool_unicode_clickable_padding"
app:layout_constraintBottom_toTopOf="@id/text_view_to"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/edit_text_from">
<ImageView
android:id="@+id/image_view_convert"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:contentDescription="@string/tool_common_convert"
android:focusable="true"
android:foreground="@drawable/foreground_ripple"
android:src="@drawable/ic_tool_arrow_down"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -4,5 +4,6 @@
xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:id="@+id/button_tool"
android:textAllCaps="false"
style="@style/ToolsButton" />
</LinearLayout>

View File

@@ -74,13 +74,20 @@
<string name="setting_about">关于</string>
<string name="setting_about_oxygen_toolbox">关于 氧工具</string>
<string name="tool_common_please_enter_text">请输入内容……</string>
<string name="tool_common_convert">转换</string>
<string name="tool_common_translation">翻译</string>
<string name="tool_common_swap">交换</string>
<string name="tool_common_choose">选择</string>
<string name="tool_translation_choose_language">选择语言</string>
<string name="tool_translation_please_enter_text">请输入内容……</string>
<string name="tool_translation_translation_failed">翻译失败,请检查网络连接。</string>
<string name="tool_baseconverter_choose_base">选择进制</string>
<string name="tool_baseconverter_from_base">源进制</string>
<string name="tool_baseconverter_to_base">目标进制</string>
<string name="tool_baseconverter_please_enter_text">请输入内容……</string>
<string name="tool_baseconverter_illegal_number">非法数字</string>
<string name="tool_unicode_text">文本</string>
<string name="tool_unicode_illegal_input">非法输入</string>
</resources>

View File

@@ -74,13 +74,20 @@
<string name="setting_about">关于</string>
<string name="setting_about_oxygen_toolbox">关于 氧工具</string>
<string name="tool_common_please_enter_text">请输入内容……</string>
<string name="tool_common_convert">转换</string>
<string name="tool_common_translation">翻译</string>
<string name="tool_common_swap">交换</string>
<string name="tool_common_choose">选择</string>
<string name="tool_translation_choose_language">选择语言</string>
<string name="tool_translation_please_enter_text">请输入内容……</string>
<string name="tool_translation_translation_failed">翻译失败,请检查网络连接。</string>
<string name="tool_baseconverter_choose_base">选择进制</string>
<string name="tool_baseconverter_from_base">源进制</string>
<string name="tool_baseconverter_to_base">目标进制</string>
<string name="tool_baseconverter_please_enter_text">请输入内容……</string>
<string name="tool_baseconverter_illegal_number">非法数字</string>
<string name="tool_unicode_text">文本</string>
<string name="tool_unicode_illegal_input">非法输入</string>
</resources>

View File

@@ -74,13 +74,20 @@
<string name="setting_about">关于</string>
<string name="setting_about_oxygen_toolbox">关于 氧工具</string>
<string name="tool_common_please_enter_text">请输入内容……</string>
<string name="tool_common_convert">转换</string>
<string name="tool_common_translation">翻译</string>
<string name="tool_common_swap">交换</string>
<string name="tool_common_choose">选择</string>
<string name="tool_translation_choose_language">选择语言</string>
<string name="tool_translation_please_enter_text">请输入内容……</string>
<string name="tool_translation_translation_failed">翻译失败,请检查网络连接。</string>
<string name="tool_baseconverter_choose_base">选择进制</string>
<string name="tool_baseconverter_from_base">源进制</string>
<string name="tool_baseconverter_to_base">目标进制</string>
<string name="tool_baseconverter_please_enter_text">请输入内容……</string>
<string name="tool_baseconverter_illegal_number">非法数字</string>
<string name="tool_unicode_text">文本</string>
<string name="tool_unicode_illegal_input">非法输入</string>
</resources>

View File

@@ -2,6 +2,7 @@
<resources>
<dimen name="common_layout_margin">10dp</dimen>
<dimen name="common_text_size">20sp</dimen>
<dimen name="common_text_size_small">16sp</dimen>
<dimen name="splash_logo_size">288dp</dimen>
@@ -38,17 +39,24 @@
<dimen name="tool_time_screen_time_height">120dp</dimen>
<dimen name="tool_time_screen_time_text_size">100sp</dimen>
<dimen name="tool_translation_text_size">16sp</dimen>
<dimen name="tool_translation_text_size">@dimen/common_text_size_small</dimen>
<dimen name="tool_translation_clickable_padding">5dp</dimen>
<dimen name="tool_translation_edit_text_view_padding">15dp</dimen>
<dimen name="tool_translation_edit_text_view_padding_plus">30dp</dimen>
<dimen name="tool_translation_layout_margin">@dimen/common_layout_margin</dimen>
<dimen name="tool_translation_edit_text_view_height">200dp</dimen>
<dimen name="tool_baseconverter_text_size">16sp</dimen>
<dimen name="tool_baseconverter_text_size">@dimen/common_text_size_small</dimen>
<dimen name="tool_baseconverter_clickable_padding">5dp</dimen>
<dimen name="tool_baseconverter_layout_margin">@dimen/common_layout_margin</dimen>
<dimen name="tool_baseconverter_edit_text_view_height">200dp</dimen>
<dimen name="tool_baseconverter_edit_text_view_padding">15dp</dimen>
<dimen name="tool_baseconverter_edit_text_view_padding_plus">30dp</dimen>
<dimen name="tool_unicode_text_size">@dimen/common_text_size_small</dimen>
<dimen name="tool_unicode_clickable_padding">5dp</dimen>
<dimen name="tool_unicode_layout_margin">@dimen/common_layout_margin</dimen>
<dimen name="tool_unicode_edit_text_view_height">200dp</dimen>
<dimen name="tool_unicode_edit_text_view_padding">15dp</dimen>
<dimen name="tool_unicode_edit_text_view_padding_plus">30dp</dimen>
</resources>

View File

@@ -108,12 +108,17 @@
<string name="tool_time_screen_colon" translatable="false">&#160;:&#160;</string>
<string name="tool_common_please_enter_text">Please enter text…</string>
<string name="tool_common_convert">Convert</string>
<string name="tool_common_translation">Translation</string>
<string name="tool_common_swap">Swap</string>
<string name="tool_common_choose">Choose</string>
<string name="tool_translation_choose_language">Choose a language</string>
<string name="tool_translation_language_chinese" translatable="false">中文</string>
<string name="tool_translation_language_english" translatable="false">English</string>
<string name="tool_translation_language_japanese" translatable="false">日本</string>
<string name="tool_translation_language_korean" translatable="false">한국인</string>
<string name="tool_translation_please_enter_text">Please enter text…</string>
<string name="tool_translation_translation_failed">Translation failed, please check network connection.</string>
<string name="tool_baseconverter_base_2" translatable="false">2 (binary)</string>
@@ -123,6 +128,10 @@
<string name="tool_baseconverter_choose_base">Choose base</string>
<string name="tool_baseconverter_from_base">From Base</string>
<string name="tool_baseconverter_to_base">To Base</string>
<string name="tool_baseconverter_please_enter_text">Please enter text…</string>
<string name="tool_baseconverter_illegal_number">Illegal Number</string>
<string name="tool_unicode_ascii" translatable="false">ASCII</string>
<string name="tool_unicode_unicode" translatable="false">Unicode</string>
<string name="tool_unicode_text">Text</string>
<string name="tool_unicode_illegal_input">Illegal Input</string>
</resources>

View File

@@ -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("安卓"), "&#23433;&#21331;");
}
@Test
public void asciiToStringTest() throws Exception {
assertEquals(Utils.asciiToString("&#23433;&#21331;"), "安卓");
}
@Test
public void stringToUnicodeTest() {
assertEquals(Utils.stringToUnicode("安卓"), "\\u5b89\\u5353");
}
@Test
public void unicodeToStringTest() throws Exception {
assertEquals(Utils.unicodeToString("\\u5b89\\u5353"), "安卓");
}
}