1
0
mirror of https://github.com/fumiama/simple-dict-android.git synced 2026-06-05 00:30:24 +08:00
This commit is contained in:
fumiama
2021-02-17 01:19:45 +08:00
parent 7c92b47501
commit cacf34544f
37 changed files with 1224 additions and 0 deletions

1
app/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

109
app/build.gradle Normal file
View File

@@ -0,0 +1,109 @@
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-android-extensions'
id 'AndResGuard'
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.2"
defaultConfig {
applicationId "top.fumiama.simpledict"
minSdkVersion 23
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
signingConfigs {
winrelease {
storeFile file('C:/Users/spayi/OneDrive/swc/developer/android_key/open_key')
storePassword 'fumiama'
keyAlias 'default'
keyPassword 'fumiama'
v1SigningEnabled true
v2SigningEnabled true
}
}
buildTypes {
winrelease {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.winrelease
}
/*debug{
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}*/
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.3'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.3'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation 'com.lapism:search:2.4.1@aar'
}
andResGuard {
// mappingFile = file("./resource_mapping.txt")
mappingFile = null
use7zip = true
useSign = true
// It will keep the origin path of your resources when it's true
keepRoot = false
// If set, name column in arsc those need to proguard will be kept to this value
fixedResName = "arg"
// It will merge the duplicated resources, but don't rely on this feature too much.
// it's always better to remove duplicated resource from repo
mergeDuplicatedRes = true
whiteList = [
"R.drawable.load",
// your icon
"R.drawable.icon",
// for fabric
"R.string.com.crashlytics.*",
// for google-services
"R.string.google_app_id",
"R.string.gcm_defaultSenderId",
"R.string.default_web_client_id",
"R.string.ga_trackingId",
"R.string.firebase_database_url",
"R.string.google_api_key",
"R.string.google_crash_reporting_api_key"
]
compressFilePattern = [
"*.png",
"*.jpg",
"*.jpeg",
"*.gif",
"resources.arsc"
]
sevenzip {
artifact = 'com.tencent.mm:SevenZip:1.2.20'
//path = "/usr/local/bin/7za"
}
}

31
app/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1,31 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-assumenosideeffects class android.util.Log {
public static *** d(...);
public static *** e(...);
public static *** i(...);
public static *** v(...);
public static *** println(...);
public static *** w(...);
public static *** wtf(...);
}

View File

@@ -0,0 +1,24 @@
package top.fumiama.simpledict
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("top.fumiama.simpledict", appContext.packageName)
}
}

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="top.fumiama.simpledict">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher"
android:supportsRtl="true"
android:theme="@style/Theme.SimpleDict"
android:usesCleartextTraffic="true">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/Theme.SimpleDict.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,94 @@
package top.fumiama.simpledict
import android.util.Log
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.net.Socket
import java.nio.charset.Charset
class Client(val ip: String, val port: Int) {
//普通数据交互接口
private var sc: Socket? = null
//普通交互流
private var dout: OutputStream? = null
private var din: InputStream? = null
//已连接标记
var isConnect = false
/**
* 初始化普通交互连接
*/
fun initConnect(){
try {
sc = Socket(ip, port) //通过socket连接服务器
din = sc?.getInputStream() //获取输入流并转换为StreamReader约定编码格式
dout = sc?.getOutputStream() //获取输出流
sc?.soTimeout = 10000 //设置连接超时限制
if (sc != null && din != null && dout != null) { //判断一下是否都连上避免NullPointException
isConnect = true
Log.d("MyC", "connect server successful")
} else {
Log.d("MyC", "connect server failed,now retry...")
initConnect()
}
} catch (e: IOException) { //获取输入输出流是可能报IOException的所以必须try-catch
e.printStackTrace()
}
}
/**
* 发送数据至服务器
* @param message 要发送至服务器的字符串
*/
fun sendMessage(message: CharSequence?) {
try {
if (isConnect) {
if (dout != null && message != null) { //判断输出流或者消息是否为空为空的话会产生nullpoint错误
dout!!.write(message.toString().toByteArray())
dout!!.flush()
} else Log.d("MyC", "The message to be sent is empty or have no connect")
Log.d("MyC", "send message succeed")
} else Log.d("MyC", "no connect to send message")
} catch (e: IOException) {
Log.d("MyC", "send message to cilent failed")
e.printStackTrace()
}
}
fun receiveMessage(): String? {
var message: String? = ""
try {
if (isConnect) {
Log.d("MyC", "开始接收服务端信息")
val inMessage = ByteArray(1024) //设置接受缓冲,避免接受数据过长占用过多内存
val a = din?.read(inMessage) //a存储返回消息的长度
if (a == null || a <= -1) return null
Log.d("MyC", "reply length:$a")
message = inMessage.copyOf(a).decodeToString()
Log.d("MyC", message)
} else Log.d("MyC", "no connect to receive message")
} catch (e: IOException) {
Log.d("MyC", "receive message failed")
e.printStackTrace()
}
return message
}
/**
* 关闭连接
*/
fun closeConnect() {
try {
din?.close()
dout?.close()
sc?.close()
} catch (e: IOException) {
e.printStackTrace()
}
isConnect = false
Log.d("MyC", "关闭连接")
}
}

View File

@@ -0,0 +1,176 @@
package top.fumiama.simpledict
import android.annotation.SuppressLint
import android.content.SharedPreferences
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import com.lapism.search.internal.SearchLayout
import com.lapism.search.util.SearchUtils
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.line_word.view.*
import java.lang.Thread.sleep
class MainActivity : AppCompatActivity() {
private var keys = arrayOf<String>()
private var datas = arrayOf<String?>()
private val dict = SimpleDict(Client("192.168.98.2", 8000))
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
ffms.apply {
setAdapterLayoutManager(LinearLayoutManager(this@MainActivity))
val adapter = ViewData(findViewById(R.id.search_recycler_view)).RecyclerViewAdapter()
setAdapter(adapter)
navigationIconSupport = SearchLayout.NavigationIconSupport.SEARCH
setOnNavigationClickListener(object : SearchLayout.OnNavigationClickListener {
override fun onNavigationClick(hasFocus: Boolean) {
if (hasFocus()) clearFocus()
else requestFocus()
}
})
setTextHint(android.R.string.search_go)
setOnQueryTextListener(object : SearchLayout.OnQueryTextListener {
val sysTime get() = System.currentTimeMillis() / 1000
var lastVisitTime = sysTime
val isLast get() = sysTime - lastVisitTime > 1
var hasLoad = true
var key: CharSequence = ""
set(value) {
field = value
lastVisitTime = sysTime
hasLoad = false
}
init {
Thread {
while (true) {
sleep(1)
if (isLast && !hasLoad) {
adapter.filter(key)
hasLoad = true
}
}
}.start()
}
override fun onQueryTextChange(newText: CharSequence): Boolean {
if (newText.isNotEmpty()) key = newText
return true
}
override fun onQueryTextSubmit(query: CharSequence): Boolean {
if(query.isNotEmpty()) Thread{
val data = dict[query]
runOnUiThread {
showDictAlert(query.toString(), data)
}
}.start()
return true
}
})
setOnMicClickListener(object : SearchLayout.OnMicClickListener {
override fun onMicClick() {
if (SearchUtils.isVoiceSearchAvailable(this@MainActivity)) {
SearchUtils.setVoiceSearch(this@MainActivity, "speak")
}
}
})
setOnFocusChangeListener(object : SearchLayout.OnFocusChangeListener {
override fun onFocusChange(hasFocus: Boolean) {
navigationIconSupport = if (hasFocus) SearchLayout.NavigationIconSupport.ARROW
else SearchLayout.NavigationIconSupport.SEARCH
}
})
}
}
override fun onBackPressed() {
if(ffms.hasFocus()) ffms.clearFocus()
else super.onBackPressed()
}
private fun showDictAlert(key: String, data: String?) {
AlertDialog.Builder(this@MainActivity)
.setTitle(key)
.setMessage(data)
.setPositiveButton(if(data != "null") "重设" else "添加") { _, _ ->
val t = EditText(this@MainActivity)
AlertDialog.Builder(this@MainActivity)
.setTitle("重设$key")
.setView(t)
.setPositiveButton(android.R.string.ok) { _, _ ->
if (t.text.isNotEmpty()) Thread {
dict[key] = t.text.toString()
}.start()
}
.setNegativeButton(android.R.string.cancel) { _, _ -> }
.show()
}
.setNeutralButton("收藏") { _, _ ->
getSharedPreferences("dict", MODE_PRIVATE)?.edit()?.let {
it.putString(key, data)
it.apply()
}
}
.setNegativeButton(android.R.string.cancel) { _, _ -> }
.show()
}
inner class ViewData(itemView: View) : RecyclerView.ViewHolder(itemView) {
inner class RecyclerViewAdapter :
RecyclerView.Adapter<ViewData>() {
var count = 0
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewData {
return ViewData(
LayoutInflater.from(parent.context)
.inflate(R.layout.line_word, parent, false)
)
}
@SuppressLint("ClickableViewAccessibility", "SetTextI18n")
override fun onBindViewHolder(holder: ViewData, position: Int) {
Log.d("MyMain", "Bind $position")
if(position < keys.size) {
holder.itemView.ta.text = keys[position]
if(position < datas.size) holder.itemView.tb.text = datas[position]
holder.itemView.setOnClickListener {
showDictAlert(keys[position], if(position < datas.size) datas[position] else "null")
}
}
}
override fun getItemCount() = count
fun filter(text: CharSequence) {
dict.pattern = text
dict.keys.let {
count = it.size
if (count > 0) {
keys = arrayOf()
datas = arrayOf()
it.forEach {
keys += it
datas += dict[it]
Log.d("MyMain", "Get key: $it is ${datas.last()}")
}
}
}
runOnUiThread { notifyDataSetChanged() }
}
}
}
}

View File

@@ -0,0 +1,55 @@
package top.fumiama.simpledict
import java.lang.Thread.sleep
class SimpleDict(private val client: Client): HashMap<String, String>() { //must run in thread
var pattern: CharSequence = "a"
private var isInit = true
override val keys: MutableSet<String>
get() {
val re = mutableSetOf<String>()
if(isInit) {
isInit = false
return re
} else {
client.initConnect()
client.sendMessage("lst")
sleep(233)
client.receiveMessage()
client.sendMessage(pattern)
client.receiveMessage()?.substringBeforeLast('\n')?.split('\n')?.forEach {
re.add(it)
}
client.sendMessage("quit")
client.closeConnect()
return re
}
}
override fun get(key: String): String? {
client.initConnect()
client.sendMessage("get")
sleep(233)
client.receiveMessage()
client.sendMessage(key)
val re = client.receiveMessage()
client.sendMessage("quit")
client.closeConnect()
return re
}
override fun put(key: String, value: String): String? {
val p = this[key]
client.initConnect()
client.sendMessage("set")
sleep(233)
client.receiveMessage()
client.sendMessage(key)
client.receiveMessage()
client.sendMessage(value)
client.receiveMessage()
client.sendMessage("quit")
client.closeConnect()
return p
}
}

View File

@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="@color/colorPrimary"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.lapism.search.widget.MaterialSearchView
android:id="@+id/ffms"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:foreground="?android:attr/selectableItemBackground"
android:orientation="vertical">
<TextView
android:id="@+id/ta"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:text="TextView"
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
android:textSize="18sp" />
<TextView
android:id="@+id/tb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:text="TextView" />
</LinearLayout>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@android:drawable/ic_menu_search" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.SimpleDict" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_200</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="colorPrimary">#BA8D08</color>
<color name="colorPrimaryVariant">#FF9800</color>
<color name="colorSecondary">#FF845E</color>
<color name="colorSecondaryVariant">#FF5722</color>
</resources>

View File

@@ -0,0 +1,3 @@
<resources>
<dimen name="fab_margin">16dp</dimen>
</resources>

View File

@@ -0,0 +1,12 @@
<resources>
<string name="app_name">SimpleDict</string>
<string name="action_settings">Settings</string>
<!-- Strings used for fragments for navigation -->
<string name="first_fragment_label">First Fragment</string>
<string name="second_fragment_label">Second Fragment</string>
<string name="next">Next</string>
<string name="previous">Previous</string>
<string name="hello_first_fragment">Hello first fragment</string>
<string name="hello_second_fragment">Hello second fragment. Arg: %1$s</string>
</resources>

View File

@@ -0,0 +1,27 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.SimpleDict" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryVariant">@color/colorPrimaryVariant</item>
<item name="colorOnPrimary">@android:color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/colorSecondary</item>
<item name="colorSecondaryVariant">@color/colorSecondaryVariant</item>
<item name="colorOnSecondary">@android:color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:windowLightStatusBar">true</item>
<!-- Customize your theme here. -->
</style>
<style name="Theme.SimpleDict.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="Theme.SimpleDict.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="Theme.SimpleDict.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
</resources>

View File

@@ -0,0 +1,17 @@
package top.fumiama.simpledict
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}