Skip to content

Commit 43d8048

Browse files
committed
refactor: UI
1 parent cf93228 commit 43d8048

36 files changed

Lines changed: 323 additions & 75 deletions

app/src/main/java/io/nekohasekai/sagernet/ui/AboutFragment.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ class AboutFragment : ToolbarFragment(R.layout.layout_about) {
7575
return MaterialAboutList.Builder()
7676
.addCard(
7777
MaterialAboutCard.Builder()
78-
.outline(false)
78+
.outline(true)
7979
.addItem(
8080
MaterialAboutActionItem.Builder()
8181
.icon(R.drawable.ic_baseline_update_24)
@@ -175,7 +175,7 @@ class AboutFragment : ToolbarFragment(R.layout.layout_about) {
175175
.build())
176176
.addCard(
177177
MaterialAboutCard.Builder()
178-
.outline(false)
178+
.outline(true)
179179
.title(R.string.project)
180180
.addItem(
181181
MaterialAboutActionItem.Builder()

app/src/main/java/io/nekohasekai/sagernet/ui/ConfigurationFragment.kt

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import androidx.activity.result.contract.ActivityResultContracts
2525
import androidx.appcompat.widget.PopupMenu
2626
import androidx.appcompat.widget.SearchView
2727
import androidx.appcompat.widget.Toolbar
28+
import androidx.core.graphics.ColorUtils
2829
import androidx.core.net.toUri
2930
import androidx.core.view.isGone
3031
import androidx.core.view.isVisible
@@ -37,6 +38,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
3738
import androidx.recyclerview.widget.RecyclerView
3839
import androidx.viewpager2.adapter.FragmentStateAdapter
3940
import androidx.viewpager2.widget.ViewPager2
41+
import com.google.android.material.card.MaterialCardView
4042
import com.google.android.material.dialog.MaterialAlertDialogBuilder
4143
import com.google.android.material.tabs.TabLayout
4244
import com.google.android.material.tabs.TabLayoutMediator
@@ -1721,14 +1723,34 @@ class ConfigurationFragment @JvmOverloads constructor(
17211723
val profileStatus: TextView = view.findViewById(R.id.profile_status)
17221724

17231725
val trafficText: TextView = view.findViewById(R.id.traffic_text)
1724-
val selectedView: LinearLayout = view.findViewById(R.id.selected_view)
1726+
private val card = view as MaterialCardView
17251727
val editButton: ImageView = view.findViewById(R.id.edit)
17261728
val doubleColumnMenuButton: ImageView = view.findViewById(R.id.double_column_menu)
17271729
val shareLayout: LinearLayout = view.findViewById(R.id.share)
17281730
val shareLayer: LinearLayout = view.findViewById(R.id.share_layer)
17291731
val shareButton: ImageView = view.findViewById(R.id.shareIcon)
17301732
val removeButton: ImageView = view.findViewById(R.id.remove)
17311733

1734+
private fun applySelected(selected: Boolean) {
1735+
val ctx = card.context
1736+
val primary = ctx.getColorAttr(R.attr.colorPrimary)
1737+
val surface = ctx.getColorAttr(R.attr.colorSurface)
1738+
card.strokeWidth = ctx.resources.getDimensionPixelSize(
1739+
if (selected) R.dimen.card_stroke_width_selected else R.dimen.card_stroke_width
1740+
)
1741+
card.strokeColor =
1742+
if (selected) primary else ctx.getColour(R.color.card_stroke)
1743+
card.setCardBackgroundColor(
1744+
if (selected) {
1745+
ColorUtils.compositeColors(
1746+
ColorUtils.setAlphaComponent(primary, 26), surface
1747+
)
1748+
} else {
1749+
surface
1750+
}
1751+
)
1752+
}
1753+
17321754
fun bind(proxyEntity: ProxyEntity, trafficData: TrafficData? = null) {
17331755
val pf = parentFragment as? ConfigurationFragment ?: return
17341756

@@ -1748,7 +1770,7 @@ class ConfigurationFragment @JvmOverloads constructor(
17481770
lastSelected = DataStore.selectedProxy
17491771
DataStore.selectedProxy = proxyEntity.id
17501772
onMainDispatcher {
1751-
selectedView.visibility = View.VISIBLE
1773+
applySelected(true)
17521774
}
17531775
}
17541776

@@ -1937,7 +1959,7 @@ class ConfigurationFragment @JvmOverloads constructor(
19371959
onMainDispatcher {
19381960
editButton.isEnabled = !started
19391961
removeButton.isEnabled = !started
1940-
selectedView.visibility = if (selected) View.VISIBLE else View.INVISIBLE
1962+
applySelected(selected)
19411963
}
19421964

19431965
if (!(select || proxyEntity.type == ProxyEntity.TYPE_CHAIN)) {

app/src/main/java/io/nekohasekai/sagernet/ui/RouteFragment.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import android.view.MenuItem
66
import android.view.View
77
import android.view.ViewGroup
88
import androidx.appcompat.widget.Toolbar
9+
import androidx.core.content.ContextCompat
910
import androidx.core.view.ViewCompat
1011
import androidx.recyclerview.widget.ItemTouchHelper
1112
import androidx.recyclerview.widget.RecyclerView
@@ -284,6 +285,16 @@ class RouteFragment : ToolbarFragment(R.layout.layout_route), Toolbar.OnMenuItem
284285
profileName.text = rule.displayName()
285286
profileType.text = rule.mkSummary()
286287
routeOutbound.text = rule.displayOutbound()
288+
289+
// 根据路由类型设置文字颜色
290+
val colorRes = when (rule.outbound) {
291+
-2L -> R.color.color_route_block // 屏蔽:红色
292+
-1L -> R.color.color_route_direct // 直连:绿色
293+
0L -> R.color.color_route_proxy // 代理:蓝色
294+
else -> R.color.color_route_config // 配置:紫色
295+
}
296+
routeOutbound.setTextColor(ContextCompat.getColor(itemView.context, colorRes))
297+
287298
itemView.setOnClickListener {
288299
enableSwitch.performClick()
289300
}

app/src/main/java/io/nekohasekai/sagernet/utils/Theme.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ object Theme {
3030
const val GREY = 19
3131
const val BLUE_GREY = 20
3232
const val BLACK = 21
33+
const val VERDANT_MINT = 22
3334

3435
private fun defaultTheme() = PINK_SSR
3536

@@ -72,6 +73,7 @@ object Theme {
7273
GREY -> R.style.Theme_SagerNet_Grey
7374
BLUE_GREY -> R.style.Theme_SagerNet_BlueGrey
7475
BLACK -> R.style.Theme_SagerNet_Black
76+
VERDANT_MINT -> R.style.Theme_SagerNet_VerdantMint
7577
else -> getTheme(defaultTheme())
7678
}
7779
}
@@ -99,6 +101,7 @@ object Theme {
99101
GREY -> R.style.Theme_SagerNet_Dialog_Grey
100102
BLUE_GREY -> R.style.Theme_SagerNet_Dialog_BlueGrey
101103
BLACK -> R.style.Theme_SagerNet_Dialog_Black
104+
VERDANT_MINT -> R.style.Theme_SagerNet_Dialog_VerdantMint
102105
else -> getDialogTheme(defaultTheme())
103106
}
104107
}

app/src/main/java/moe/matsuri/nb4a/ui/SimpleMenuPreference.kt

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@
1717
package moe.matsuri.nb4a.ui
1818

1919
import android.content.Context
20+
import android.graphics.drawable.GradientDrawable
2021
import android.util.AttributeSet
2122
import android.view.View
2223
import android.view.ViewGroup
2324
import android.widget.ArrayAdapter
2425
import android.widget.Spinner
25-
import androidx.core.content.ContextCompat
2626
import androidx.preference.DropDownPreference
2727
import androidx.preference.PreferenceViewHolder
2828
import io.nekohasekai.sagernet.R
@@ -48,6 +48,7 @@ open class SimpleMenuPreference
4848
super.onBindViewHolder(holder)
4949
val mSpinner = holder.itemView.findViewById<Spinner>(R.id.spinner)
5050
mSpinner.layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT
51+
mSpinner.setPopupBackgroundResource(R.drawable.bg_spinner_dropdown)
5152
}
5253

5354
override fun createAdapter(): ArrayAdapter<CharSequence?> {
@@ -68,19 +69,42 @@ open class SimpleMenuPreference
6869

6970
var currentPosition = -1
7071

72+
private val radius = 12f * context.resources.displayMetrics.density
73+
private val selectedColor = context.getColorAttr(R.attr.colorMaterial100)
74+
75+
private val topDrawable = GradientDrawable().apply {
76+
setColor(selectedColor)
77+
cornerRadii = floatArrayOf(radius, radius, radius, radius, 0f, 0f, 0f, 0f)
78+
}
79+
80+
private val bottomDrawable = GradientDrawable().apply {
81+
setColor(selectedColor)
82+
cornerRadii = floatArrayOf(0f, 0f, 0f, 0f, radius, radius, radius, radius)
83+
}
84+
85+
private val middleDrawable = GradientDrawable().apply {
86+
setColor(selectedColor)
87+
}
88+
89+
private val singleDrawable = GradientDrawable().apply {
90+
setColor(selectedColor)
91+
cornerRadii = floatArrayOf(radius, radius, radius, radius, radius, radius, radius, radius)
92+
}
93+
7194
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
7295
val view: View = super.getDropDownView(position, convertView, parent)
96+
7397
if (position == currentPosition) {
74-
view.setBackgroundColor(context.getColorAttr(R.attr.colorMaterial100))
98+
view.background = when {
99+
position == 0 && count == 1 -> singleDrawable
100+
position == 0 -> topDrawable
101+
position == count - 1 -> bottomDrawable
102+
else -> middleDrawable
103+
}
75104
} else {
76-
view.setBackgroundColor(
77-
ContextCompat.getColor(
78-
context,
79-
R.color.preference_simple_menu_background
80-
)
81-
)
105+
view.background = null
82106
}
83107
return view
84108
}
85109
}
86-
}
110+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<set xmlns:android="http://schemas.android.com/apk/res/android">
3+
<alpha
4+
android:fromAlpha="0.0"
5+
android:toAlpha="1.0"
6+
android:duration="150" />
7+
<scale
8+
android:fromXScale="0.95"
9+
android:toXScale="1.0"
10+
android:fromYScale="0.95"
11+
android:toYScale="1.0"
12+
android:pivotX="50%"
13+
android:pivotY="0%"
14+
android:duration="150" />
15+
</set>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<set xmlns:android="http://schemas.android.com/apk/res/android">
3+
<alpha
4+
android:fromAlpha="1.0"
5+
android:toAlpha="0.0"
6+
android:duration="100" />
7+
<scale
8+
android:fromXScale="1.0"
9+
android:toXScale="0.95"
10+
android:fromYScale="1.0"
11+
android:toYScale="0.95"
12+
android:pivotX="50%"
13+
android:pivotY="0%"
14+
android:duration="100" />
15+
</set>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<selector xmlns:android="http://schemas.android.com/apk/res/android">
3+
<item android:color="?attr/colorPrimary" android:alpha="0.16" android:state_checked="true" />
4+
<item android:color="@android:color/transparent" />
5+
</selector>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<shape xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:shape="rectangle">
4+
<corners android:radius="@dimen/dialog_corner_radius" />
5+
<solid android:color="?attr/colorSurface" />
6+
</shape>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<shape xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:shape="rectangle">
4+
<corners android:radius="@dimen/popup_corner_radius" />
5+
<solid android:color="?attr/colorSurface" />
6+
<stroke
7+
android:width="@dimen/card_stroke_width"
8+
android:color="@color/card_stroke" />
9+
</shape>

0 commit comments

Comments
 (0)