1
0
mirror of https://github.com/fumiama/simple-dict-android.git synced 2026-06-10 21:24:20 +08:00

1. 增加小部件

2. 调整间距
3. 增加设置
4. 界面美化
This commit is contained in:
fumiama
2021-03-21 00:49:27 +08:00
parent 750f071e1f
commit 44c5d8b5ef
10 changed files with 228 additions and 41 deletions

View File

@@ -12,8 +12,8 @@ android {
applicationId "top.fumiama.simpledict" applicationId "top.fumiama.simpledict"
minSdkVersion 26 minSdkVersion 26
targetSdkVersion 30 targetSdkVersion 30
versionCode 9 versionCode 10
versionName '1.7' versionName '1.8'
resConfigs "zh", "zh-rCN" resConfigs "zh", "zh-rCN"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

Binary file not shown.

View File

@@ -10,8 +10,8 @@
{ {
"type": "SINGLE", "type": "SINGLE",
"filters": [], "filters": [],
"versionCode": 9, "versionCode": 10,
"versionName": "1.7", "versionName": "1.8",
"outputFile": "app-release.apk" "outputFile": "app-release.apk"
} }
] ]

View File

@@ -4,9 +4,7 @@ import android.annotation.SuppressLint
import android.content.ClipData import android.content.ClipData
import android.content.ClipboardManager import android.content.ClipboardManager
import android.content.Context import android.content.Context
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.speech.RecognizerIntent
import android.text.SpannableString import android.text.SpannableString
import android.text.Spanned import android.text.Spanned
import android.text.style.StrikethroughSpan import android.text.style.StrikethroughSpan
@@ -18,16 +16,22 @@ import android.widget.EditText
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.edit
import androidx.core.view.children import androidx.core.view.children
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.lapism.search.internal.SearchLayout import com.lapism.search.internal.SearchLayout
import com.lapism.search.util.SearchUtils
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.dialog_input.view.*
import kotlinx.android.synthetic.main.line_word.view.* import kotlinx.android.synthetic.main.line_word.view.*
import java.io.FileNotFoundException
import java.lang.Exception
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
private val dict = SimpleDict(Client("127.0.0.1", 8000), "fumiama") private var host = "127.0.0.1"
private var port = 80
private var pwd = "demo"
private var dict: SimpleDict? = null
private var hasLiked = false private var hasLiked = false
private var cm: ClipboardManager? = null private var cm: ClipboardManager? = null
private var ad: ListViewHolder.RecyclerViewAdapter? = null private var ad: ListViewHolder.RecyclerViewAdapter? = null
@@ -35,6 +39,12 @@ class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
getSharedPreferences("remote", MODE_PRIVATE)?.apply {
if(contains("host")) getString("host", host)?.apply { host = this }
if(contains("port")) getInt("port", port).apply { port = this }
if(contains("pwd")) getString("pwd", pwd)?.apply { pwd = this }
}
dict = SimpleDict(Client(host, port), pwd)
ad = LikeViewHolder(ffr).RecyclerViewAdapter() ad = LikeViewHolder(ffr).RecyclerViewAdapter()
cm = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager cm = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
ffr.apply { ffr.apply {
@@ -58,6 +68,7 @@ class MainActivity : AppCompatActivity() {
val adapter = SearchViewHolder(recyclerView, findViewById(R.id.search_search_edit_text)).RecyclerViewAdapter() val adapter = SearchViewHolder(recyclerView, findViewById(R.id.search_search_edit_text)).RecyclerViewAdapter()
setAdapter(adapter) setAdapter(adapter)
navigationIconSupport = SearchLayout.NavigationIconSupport.SEARCH navigationIconSupport = SearchLayout.NavigationIconSupport.SEARCH
setMicIconImageResource(R.drawable.ic_setting)
setOnNavigationClickListener(object : SearchLayout.OnNavigationClickListener { setOnNavigationClickListener(object : SearchLayout.OnNavigationClickListener {
override fun onNavigationClick(hasFocus: Boolean) { override fun onNavigationClick(hasFocus: Boolean) {
if (hasFocus()) { if (hasFocus()) {
@@ -77,22 +88,59 @@ class MainActivity : AppCompatActivity() {
override fun onQueryTextSubmit(query: CharSequence): Boolean { override fun onQueryTextSubmit(query: CharSequence): Boolean {
if(query.isNotEmpty()) { if(query.isNotEmpty()) {
val key = query.toString() val key = query.toString()
val data = dict[key] val data = dict?.get(key)
showDictAlert(key, data, recyclerView.children.toList().let { showDictAlert(key, data, recyclerView.children.toList().let {
val i = it.map { it.ta.text }.indexOf(key) val i = it.map { it.ta.text }.indexOf(key)
if(i >= 0) it[i] else null if(i >= 0) it[i] else null
}) { adapter.refresh() } })
} }
return true return true
} }
}) })
setOnMicClickListener(object : SearchLayout.OnMicClickListener { setOnMicClickListener(object : SearchLayout.OnMicClickListener {
override fun onMicClick() { override fun onMicClick() {
if (SearchUtils.isVoiceSearchAvailable(this@MainActivity)) { /*if (SearchUtils.isVoiceSearchAvailable(this@MainActivity)) {
SearchUtils.setVoiceSearch(this@MainActivity, "please speak") SearchUtils.setVoiceSearch(this@MainActivity, "please speak")
} }*/
val t = layoutInflater.inflate(R.layout.dialog_input, null, false)
AlertDialog.Builder(this@MainActivity)
.setView(t)
.setTitle("提示")
.setPositiveButton(android.R.string.ok) { _, _ ->
val info = t.diet.text.toString()
try {
val h = info.substringBefore(':')
val l = info.substringAfter(':')
val p = l.substringBefore('_').toInt()
val w = l.substringAfter('_')
if (h != "" && p > 0 && p < 65536 && w != "") {
getSharedPreferences("remote", MODE_PRIVATE)?.edit {
putString("host", h)
putInt("port", p)
putString("pwd", w)
apply()
Toast.makeText(this@MainActivity, "下次生效", Toast.LENGTH_SHORT).show()
return@setPositiveButton
}
throw FileNotFoundException("getSharedPreferences named \"remote\" error.")
} else throw IllegalArgumentException()
} catch (e: Exception) {
e.printStackTrace()
Toast.makeText(this@MainActivity, "格式非法", Toast.LENGTH_SHORT).show()
}
}
.setNegativeButton(android.R.string.cancel) { _, _ -> }
.show()
} }
}) })
setOnClearClickListener(object : SearchLayout.OnClearClickListener {
override fun onClearClick() {
Toast.makeText(this@MainActivity, "clear", Toast.LENGTH_SHORT).show()
}
})
setOnFocusChangeListener(object : SearchLayout.OnFocusChangeListener { setOnFocusChangeListener(object : SearchLayout.OnFocusChangeListener {
override fun onFocusChange(hasFocus: Boolean) { override fun onFocusChange(hasFocus: Boolean) {
navigationIconSupport = if (hasFocus) SearchLayout.NavigationIconSupport.ARROW navigationIconSupport = if (hasFocus) SearchLayout.NavigationIconSupport.ARROW
@@ -110,7 +158,7 @@ class MainActivity : AppCompatActivity() {
else super.onBackPressed() else super.onBackPressed()
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { /*override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data) super.onActivityResult(requestCode, resultCode, data)
when(requestCode) { when(requestCode) {
SearchUtils.SPEECH_REQUEST_CODE -> data?.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)?.let { SearchUtils.SPEECH_REQUEST_CODE -> data?.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)?.let {
@@ -120,11 +168,11 @@ class MainActivity : AppCompatActivity() {
} }
} }
} }
} }*/
private fun fetchThread() { private fun fetchThread() {
Thread{ Thread{
dict.fetchDict { dict?.fetchDict {
runOnUiThread { runOnUiThread {
Toast.makeText(this@MainActivity, "刷新成功", Toast.LENGTH_SHORT).show() Toast.makeText(this@MainActivity, "刷新成功", Toast.LENGTH_SHORT).show()
ffsw.isRefreshing = false ffsw.isRefreshing = false
@@ -134,22 +182,23 @@ class MainActivity : AppCompatActivity() {
}.start() }.start()
} }
private fun showDictAlert(key: String, data: String?, line: View?, refresh: (()->Unit)?=null) { private fun showDictAlert(key: String, data: String?, line: View?) {
val hintAdd = if(data != null && data != "null") "重设" else "添加" val hintAdd = if(data != null && data != "null") "重设" else "添加"
hasLiked = false hasLiked = false
AlertDialog.Builder(this@MainActivity) AlertDialog.Builder(this@MainActivity)
.setTitle(key) .setTitle(key)
.setMessage(data) .setMessage(data)
.setPositiveButton(hintAdd) { _, _ -> .setPositiveButton(hintAdd) { _, _ ->
val t = EditText(this@MainActivity) val t = layoutInflater.inflate(R.layout.dialog_input, null, false)
t.setText(data) t.diet.setText(data)
t.dit.text = "更改将立即生效"
AlertDialog.Builder(this@MainActivity) AlertDialog.Builder(this@MainActivity)
.setTitle("$hintAdd$key") .setTitle("$hintAdd$key")
.setView(t) .setView(t)
.setPositiveButton(android.R.string.ok) { _, _ -> .setPositiveButton(android.R.string.ok) { _, _ ->
val newText = t.text.toString() val newText = t.diet.text.toString()
if (t.text.isNotEmpty() && newText != data) Thread { if (t.diet.text.isNotEmpty() && newText != data) Thread {
dict[key] = newText dict?.set(key, newText)
line?.tb?.text = newText line?.tb?.text = newText
}.start() }.start()
else Toast.makeText(this, "未更改", Toast.LENGTH_SHORT).show() else Toast.makeText(this, "未更改", Toast.LENGTH_SHORT).show()
@@ -159,7 +208,7 @@ class MainActivity : AppCompatActivity() {
} }
.setNeutralButton("删除") { _, _ -> .setNeutralButton("删除") { _, _ ->
Thread{ Thread{
dict -= key dict?.minusAssign(key)
line?.apply { line?.apply {
val delKey = SpannableString(key) val delKey = SpannableString(key)
val delData = SpannableString(data) val delData = SpannableString(data)
@@ -178,17 +227,16 @@ class MainActivity : AppCompatActivity() {
inner class SearchViewHolder(itemView: View, private val editText: EditText) : ListViewHolder(itemView) { inner class SearchViewHolder(itemView: View, private val editText: EditText) : ListViewHolder(itemView) {
inner class RecyclerViewAdapter : ListViewHolder.RecyclerViewAdapter() { inner class RecyclerViewAdapter : ListViewHolder.RecyclerViewAdapter() {
override fun getKeys() = filter(editText.text) override fun getKeys() = filter(editText.text)
override fun getValue(key: String) = dict[key] override fun getValue(key: String) = dict?.get(key)
private fun filter(text: CharSequence): List<String> { private fun filter(text: CharSequence): List<String> {
val selectSet = dict.keys.filter { it.contains(text, true) }.toSet() + val selectSet = dict?.keys?.filter { it.contains(text, true) }?.toSet()?.plus(dict?.filterValues { it?.contains(text, true) ?: false }.let {
dict.filterValues { it?.contains(text, true) ?: false }.let { val newSet = mutableSetOf<String>()
val newSet = mutableSetOf<String>() it?.keys?.forEach {
it.keys.forEach { newSet += it
newSet += it }
} newSet
newSet })
} return selectSet?.toList()?.let { if (it.size > 50) it.subList(0, 49) else it }?: emptyList()
return selectSet.toList().let { if (it.size > 50) it.subList(0, 49) else it }
} }
} }
} }
@@ -196,11 +244,13 @@ class MainActivity : AppCompatActivity() {
inner class LikeViewHolder(itemView: View) : ListViewHolder(itemView) { inner class LikeViewHolder(itemView: View) : ListViewHolder(itemView) {
inner class RecyclerViewAdapter: ListViewHolder.RecyclerViewAdapter(){ inner class RecyclerViewAdapter: ListViewHolder.RecyclerViewAdapter(){
override fun getKeys() = getSharedPreferences("dict", MODE_PRIVATE).all.keys.toTypedArray().let{ override fun getKeys() = getSharedPreferences("dict", MODE_PRIVATE).all.keys.toTypedArray().let{
val end = dict.latestKeys.size dict?.let { d ->
val start = if(end > 5) end - 5 else 0 val end = d.latestKeys.size
(dict.latestKeys.copyOfRange(start, end) + it).toList() val start = if(end > 5) end - 5 else 0
(d.latestKeys.copyOfRange(start, end) + it).toList()
}?: emptyList()
} }
override fun getValue(key: String) = dict[key]?:getSharedPreferences("dict", MODE_PRIVATE).getString(key, "null") override fun getValue(key: String) = dict?.get(key)?:getSharedPreferences("dict", MODE_PRIVATE).getString(key, "null")
} }
} }

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="rectangle" >
<!-- 填充的颜色 -->
<solid android:color="@android:color/transparent" />
<!-- 设置按钮的四个角为弧形 -->
<!-- android:radius 弧形的半径 -->
<corners android:radius="16dip" />
<!-- paddingButton里面的文字与Button边界的间隔 -->
<padding android:bottom="1dp" android:left="1dp" android:right="1dp" android:top="1dp" />
</shape>
</item>
<item android:state_pressed="false">
<shape android:shape="rectangle" >
<!-- 填充的颜色 -->
<solid android:color="@android:color/transparent" />
<!-- 设置按钮的四个角为弧形 -->
<!-- android:radius 弧形的半径 -->
<corners android:radius="16dip" />
<!-- stroke 设置边框显示 -->
<stroke
android:dashGap="0dp"
android:width="1dp"
android:color="?attr/colorOnSurface" />
<!-- paddingButton里面的文字与Button边界的间隔 -->
<padding android:bottom="1dp" android:left="1dp" android:right="1dp" android:top="1dp" />
</shape>
</item>
</selector>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="?android:textColorSecondary"
android:pathData="M944 552l-182 331a74 74 0 0 1-65 38h-362a74 74 0 0 1-65-38l-182-331a75 75 0 0 1 0-73l182-331a74 74 0 0 1 65-38h362a74 74 0 0 1 65 38l182 331a75 75 0 0 1 0 73z m-56-31a11 11 0 0 0 0-10l-182-331a11 11 0 0 0-9-5H336a11 11 0 0 0-9 5l-182 331a11 11 0 0 0 0 10l182 331a11 11 0 0 0 9 5h362a11 11 0 0 0 9-5l182-331zM514 683c-94 0-171-76-171-171s76-171 171-171c94 0 171 76 171 171s-76 171-171 171z m0-64c59 0 107-48 107-107s-48-107-107-107-107 48-107 107 48 107 107 107z"/>
</vector>

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@@ -15,10 +16,35 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ffr"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="32dp"
app:layout_constraintBottom_toBottomOf="@+id/ffr"
app:layout_constraintEnd_toEndOf="parent"
app:srcCompat="@drawable/bg_dere" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/nisi"
android:text="hv#st"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="@+id/ffr"
app:layout_constraintEnd_toStartOf="@+id/imageView" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/ffr"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

View File

@@ -0,0 +1,58 @@
<?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="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="24dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="24dp"
android:background="@drawable/bg_rnd"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:srcCompat="@drawable/bg_dere" />
<TextView
android:id="@+id/dit"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:text="请输入:服务器地址:端口_口令"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@+id/diet"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/diet"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="16dp"
android:ems="10"
android:inputType="textPersonName"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/dit"
app:layout_constraintStart_toStartOf="@+id/dit"
app:layout_constraintTop_toBottomOf="@+id/dit" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -17,8 +17,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginTop="16dp" android:layout_marginTop="10dp"
android:layout_marginEnd="10dp" android:layout_marginEnd="16dp"
android:fontFamily="@font/nisi" android:fontFamily="@font/nisi"
android:textColor="?attr/colorOnSurface" android:textColor="?attr/colorOnSurface"
android:textSize="30sp" android:textSize="30sp"