Prettified devices

This commit is contained in:
Nikonell
2023-06-24 22:10:50 +07:00
parent 5609190f72
commit fc5d6e91d4
13 changed files with 73 additions and 38 deletions

View File

@@ -1,3 +1,3 @@
package com.listerk.helible package com.listerk.helible
data class BleDevice(val name: String, val address: String, val rssi: Int) data class BleDevice(val name: String, val address: String, var rssi: Int)

View File

@@ -12,6 +12,7 @@ import androidx.recyclerview.widget.RecyclerView
class BleDeviceAdapter(private val devices: List<BleDevice>, private val gotoControlBtn: Button) : class BleDeviceAdapter(private val devices: List<BleDevice>, private val gotoControlBtn: Button) :
RecyclerView.Adapter<BleDeviceAdapter.BleDeviceViewHolder>() { RecyclerView.Adapter<BleDeviceAdapter.BleDeviceViewHolder>() {
private lateinit var itemView: View private lateinit var itemView: View
private var selectedPosition = -1
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BleDeviceViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BleDeviceViewHolder {
itemView = LayoutInflater.from(parent.context).inflate(R.layout.item_ble_device, parent, false) itemView = LayoutInflater.from(parent.context).inflate(R.layout.item_ble_device, parent, false)
@@ -24,9 +25,14 @@ class BleDeviceAdapter(private val devices: List<BleDevice>, private val gotoCon
holder.nameView.text = devices[position].name holder.nameView.text = devices[position].name
holder.addressView.text = devices[position].address holder.addressView.text = devices[position].address
holder.rssiView.text = devices[position].rssi.toString() holder.rssiView.text = devices[position].rssi.toString()
holder.cardView.isSelected = position == selectedPosition
holder.cardView.setOnClickListener { holder.cardView.setOnClickListener {
AppState.bleDevice = devices[position] AppState.bleDevice = devices[position]
gotoControlBtn.isEnabled = true gotoControlBtn.isEnabled = true
notifyItemChanged(selectedPosition)
selectedPosition = holder.adapterPosition
notifyItemChanged(selectedPosition)
} }
} }

View File

@@ -6,13 +6,16 @@ import android.widget.SeekBar
import android.widget.TextView import android.widget.TextView
class ControlActivity : AppCompatActivity() { class ControlActivity : AppCompatActivity() {
private var sliderR1Value = 0
private var sliderR2Value = 0
private var sliderR3Value = 0
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_control) setContentView(R.layout.activity_control)
var sliderR1Value = 0 val deviceNameText = findViewById<TextView>(R.id.controlDeviceName)
var sliderR2Value = 0 deviceNameText.text = getString(R.string.control_device_text, AppState.bleDevice.name)
var sliderR3Value = 0
val sliderR1ValueText = findViewById<TextView>(R.id.sliderR1Value) val sliderR1ValueText = findViewById<TextView>(R.id.sliderR1Value)
val sliderR2ValueText = findViewById<TextView>(R.id.sliderR2Value) val sliderR2ValueText = findViewById<TextView>(R.id.sliderR2Value)
@@ -28,12 +31,8 @@ class ControlActivity : AppCompatActivity() {
val val_text = getString(R.string.r_slider_text, 1, progress) val val_text = getString(R.string.r_slider_text, 1, progress)
sliderR1ValueText.text = val_text sliderR1ValueText.text = val_text
} }
override fun onStartTrackingTouch(p0: SeekBar?) {}
override fun onStartTrackingTouch(seekBar: SeekBar?) {} override fun onStopTrackingTouch(p0: SeekBar?) {}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
}
}) })
sliderR2.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { sliderR2.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
@@ -42,12 +41,8 @@ class ControlActivity : AppCompatActivity() {
val val_text = getString(R.string.r_slider_text, 2, progress) val val_text = getString(R.string.r_slider_text, 2, progress)
sliderR2ValueText.text = val_text sliderR2ValueText.text = val_text
} }
override fun onStartTrackingTouch(p0: SeekBar?) {}
override fun onStartTrackingTouch(seekBar: SeekBar?) {} override fun onStopTrackingTouch(p0: SeekBar?) {}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
}
}) })
sliderR3.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { sliderR3.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
@@ -56,12 +51,8 @@ class ControlActivity : AppCompatActivity() {
val val_text = getString(R.string.r_slider_text, 3, progress) val val_text = getString(R.string.r_slider_text, 3, progress)
sliderR3ValueText.text = val_text sliderR3ValueText.text = val_text
} }
override fun onStartTrackingTouch(p0: SeekBar?) {}
override fun onStartTrackingTouch(seekBar: SeekBar?) {} override fun onStopTrackingTouch(p0: SeekBar?) {}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
}
}) })
} }
} }

View File

@@ -38,11 +38,15 @@ class MainActivity : AppCompatActivity() {
if (result.device.name.isNullOrBlank()) { if (result.device.name.isNullOrBlank()) {
return return
} }
val deviceExists = foundDevices.any { it.address == result.device.address }
if (!deviceExists) { var deviceIndex = foundDevices.indexOfFirst { it.address == result.device.address }
if (deviceIndex < 0) {
deviceIndex = foundDevices.size
foundDevices.add(BleDevice(result.device.name, result.device.address, result.rssi)) foundDevices.add(BleDevice(result.device.name, result.device.address, result.rssi))
bleDevicesView.adapter?.notifyItemChanged(foundDevices.size - 1) } else {
foundDevices[deviceIndex].rssi = result.rssi
} }
bleDevicesView.adapter?.notifyItemChanged(deviceIndex)
} }
} }
@@ -59,16 +63,24 @@ class MainActivity : AppCompatActivity() {
val bleDevicesView = findViewById<RecyclerView>(R.id.bleDevicesView) val bleDevicesView = findViewById<RecyclerView>(R.id.bleDevicesView)
bleDevicesView.layoutManager = LinearLayoutManager(this) bleDevicesView.layoutManager = LinearLayoutManager(this)
bleDevicesView.adapter = BleDeviceAdapter(foundDevices, gotoControlButton) bleDevicesView.adapter = BleDeviceAdapter(foundDevices, gotoControlButton)
bleDevicesView.itemAnimator = null
bleScanner.startScan(leScanCallback)
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this@MainActivity, arrayOf(Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT), 1) ActivityCompat.requestPermissions(this@MainActivity, arrayOf(Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT), 1)
} else {
bleScanner.startScan(leScanCallback)
} }
} }
override fun onPause() {
super.onPause()
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this@MainActivity, arrayOf(Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT), 1)
} else {
bleScanner.stopScan(leScanCallback)
}
}
} }

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true">
<shape>
<solid android:color="?attr/selectedBlockColor" />
<corners android:radius="20dp"/>
</shape>
</item>
<item android:state_selected="false">
<shape>
<solid android:color="?attr/baseBlockColor" />
<corners android:radius="20dp"/>
</shape>
</item>
</selector>

View File

@@ -7,10 +7,10 @@
tools:context=".MainActivity"> tools:context=".MainActivity">
<TextView <TextView
android:id="@+id/helloText" android:id="@+id/controlDeviceName"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Hello helicopter!" android:text="Устройство не задано"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@@ -21,7 +21,7 @@
android:layout_width="300dp" android:layout_width="300dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:max="65535" android:max="65535"
app:layout_constraintTop_toBottomOf="@+id/helloText" app:layout_constraintTop_toBottomOf="@+id/controlDeviceName"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" /> app:layout_constraintStart_toStartOf="parent" />

View File

@@ -25,6 +25,7 @@
app:layout_constraintTop_toBottomOf="@id/devicesTitle" app:layout_constraintTop_toBottomOf="@id/devicesTitle"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="4dp"
tools:listitem="@layout/item_ble_device" /> tools:listitem="@layout/item_ble_device" />
<Button <Button

View File

@@ -4,8 +4,11 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="12dp"
android:layout_marginVertical="4dp"
android:paddingHorizontal="12dp" android:paddingHorizontal="12dp"
android:paddingVertical="4dp"> android:paddingVertical="8dp"
android:background="@drawable/ble_device_bg">
<TextView <TextView
android:id="@+id/deviceName" android:id="@+id/deviceName"

View File

@@ -1,7 +1,7 @@
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. --> <!-- Base application theme. -->
<style name="Base.Theme.HeliBLE" parent="Theme.Material3.DayNight.NoActionBar"> <style name="Base.Theme.HeliBLE" parent="Theme.Material3.DayNight.NoActionBar">
<!-- Customize your dark theme here. --> <item name="baseBlockColor">@color/material_dynamic_neutral30</item>
<!-- <item name="colorPrimary">@color/my_dark_primary</item> --> <item name="selectedBlockColor">@color/material_dynamic_neutral20</item>
</style> </style>
</resources> </resources>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="baseBlockColor" type="reference" />
<attr name="selectedBlockColor" type="reference" />
</resources>

View File

@@ -1,4 +1,5 @@
<resources> <resources>
<string name="app_name">HeliBLE</string> <string name="app_name">HeliBLE</string>
<string name="r_slider_text">R%1$d: %2$d / 65536</string> <string name="r_slider_text">R%1$d: %2$d / 65536</string>
<string name="control_device_text">Устройство: %1$s</string>
</resources> </resources>

View File

@@ -1,8 +1,8 @@
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. --> <!-- Base application theme. -->
<style name="Base.Theme.HeliBLE" parent="Theme.Material3.DayNight.NoActionBar"> <style name="Base.Theme.HeliBLE" parent="Theme.Material3.DayNight.NoActionBar">
<!-- Customize your light theme here. --> <item name="baseBlockColor">@color/material_dynamic_neutral90</item>
<!-- <item name="colorPrimary">@color/my_light_primary</item> --> <item name="selectedBlockColor">@color/material_dynamic_neutral80</item>
</style> </style>
<style name="Theme.HeliBLE" parent="Base.Theme.HeliBLE" /> <style name="Theme.HeliBLE" parent="Base.Theme.HeliBLE" />

View File

@@ -1,6 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins { plugins {
id 'com.android.application' version '8.0.1' apply false id 'com.android.application' version '8.0.2' apply false
id 'com.android.library' version '8.0.1' apply false id 'com.android.library' version '8.0.2' apply false
id 'org.jetbrains.kotlin.android' version '1.8.20' apply false id 'org.jetbrains.kotlin.android' version '1.8.20' apply false
} }