node list view kinda works

pull/12/head
geeksville 2020-04-08 15:25:57 -07:00
rodzic 737b98076a
commit 0ff97ba3c4
8 zmienionych plików z 182 dodań i 39 usunięć

Wyświetl plik

@ -77,6 +77,8 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.2.0'
implementation "androidx.fragment:fragment-ktx:1.2.4"
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'
implementation 'com.google.android.material:material:1.1.0'
implementation 'androidx.viewpager2:viewpager2:1.0.0'

Wyświetl plik

@ -30,6 +30,7 @@ import com.geeksville.mesh.model.UIViewModel
import com.geeksville.mesh.service.*
import com.geeksville.mesh.ui.ChannelFragment
import com.geeksville.mesh.ui.MapFragment
import com.geeksville.mesh.ui.UsersFragment
import com.geeksville.util.Exceptions
import com.geeksville.util.exceptionReporter
import com.google.android.gms.auth.api.signin.GoogleSignIn
@ -112,6 +113,11 @@ class MainActivity : AppCompatActivity(), Logging,
// private val tabIndexes = generateSequence(0) { it + 1 } FIXME, instead do withIndex or zip? to get the ids below, also stop duplicating strings
private val tabInfos = arrayOf(
TabInfo(
"Users",
R.drawable.ic_twotone_people_24,
UsersFragment()
),
TabInfo(
"Channel",
R.drawable.ic_twotone_contactless_24,
@ -128,10 +134,7 @@ class MainActivity : AppCompatActivity(), Logging,
R.drawable.ic_twotone_message_24,
ComposeFragment("Messages", 1) { MessagesContent() }),
TabInfo(
"Users",
R.drawable.ic_twotone_people_24,
ComposeFragment("Users", 3) { UsersContent() }),
TabInfo(
"Settings",
R.drawable.ic_twotone_settings_applications_24,
@ -470,9 +473,12 @@ class MainActivity : AppCompatActivity(), Logging,
ServiceClient<com.geeksville.mesh.IMeshService>({
com.geeksville.mesh.IMeshService.Stub.asInterface(it)
}) {
override fun onConnected(service: com.geeksville.mesh.IMeshService) {
override fun onConnected(service: com.geeksville.mesh.IMeshService) = exceptionReporter {
model.meshService = service
debug("Getting latest radioconfig from service")
model.radioConfig.value = MeshProtos.RadioConfig.parseFrom(service.radioConfig)
// We don't start listening for packets until after we are connected to the service
registerMeshReceiver()

Wyświetl plik

@ -59,22 +59,6 @@ class UIViewModel : ViewModel(), Logging {
/// various radio settings (including the channel)
val radioConfig = object : MutableLiveData<MeshProtos.RadioConfig?>(null) {
/**
* Called when the number of active observers change to 1 from 0.
*
*
* This callback can be used to know that this LiveData is being used thus should be kept
* up to date.
*/
override fun onActive() {
super.onActive()
// Get the current radio config from the service
meshService?.let {
debug("Getting latest radioconfig from service")
value = MeshProtos.RadioConfig.parseFrom(it.radioConfig)
}
}
}
override fun onCleared() {

Wyświetl plik

@ -17,9 +17,6 @@ import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.channel_fragment.*
object ChannelLog : Logging
class ChannelFragment : ScreenFragment("Channel"), Logging {
private val model: UIViewModel by activityViewModels()
@ -67,7 +64,7 @@ class ChannelFragment : ScreenFragment("Channel"), Logging {
channelNameEdit.visibility = View.VISIBLE
channelNameEdit.setText(channel.name)
editableCheckbox.isEnabled = true
qrView.setImageBitmap(channel.getChannelQR())
// Share this particular channel if someone clicks share
shareButton.setOnClickListener {

Wyświetl plik

@ -1,24 +1,133 @@
package com.geeksville.mesh.ui
/*
import androidx.compose.Composable
import androidx.ui.core.ContextAmbient
import androidx.ui.foundation.Text
import androidx.ui.layout.Column
import androidx.ui.layout.LayoutPadding
import androidx.ui.layout.Row
import androidx.ui.material.Button
import androidx.ui.unit.dp
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.geeksville.android.Logging
import com.geeksville.mesh.NodeInfo
import com.geeksville.mesh.R
import com.geeksville.mesh.model.NodeDB
import com.geeksville.mesh.model.UIState
import com.geeksville.mesh.service.MeshService
import com.geeksville.mesh.service.RadioInterfaceService
import com.geeksville.mesh.service.SoftwareUpdateService
import com.geeksville.mesh.model.UIViewModel
import kotlinx.android.synthetic.main.adapter_node_layout.view.*
import kotlinx.android.synthetic.main.nodelist_fragment.*
class UsersFragment : ScreenFragment("Users"), Logging {
private val model: UIViewModel by activityViewModels()
// Provide a direct reference to each of the views within a data item
// Used to cache the views within the item layout for fast access
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val nodeNameView = itemView.nodeNameView
}
private val nodesAdapter = object : RecyclerView.Adapter<ViewHolder>() {
/**
* Called when RecyclerView needs a new [ViewHolder] of the given type to represent
* an item.
*
*
* This new ViewHolder should be constructed with a new View that can represent the items
* of the given type. You can either create a new View manually or inflate it from an XML
* layout file.
*
*
* The new ViewHolder will be used to display items of the adapter using
* [.onBindViewHolder]. Since it will be re-used to display
* different items in the data set, it is a good idea to cache references to sub views of
* the View to avoid unnecessary [View.findViewById] calls.
*
* @param parent The ViewGroup into which the new View will be added after it is bound to
* an adapter position.
* @param viewType The view type of the new View.
*
* @return A new ViewHolder that holds a View of the given view type.
* @see .getItemViewType
* @see .onBindViewHolder
*/
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(requireContext())
// Inflate the custom layout
// Inflate the custom layout
val contactView: View = inflater.inflate(R.layout.adapter_node_layout, parent, false)
// Return a new holder instance
return ViewHolder(contactView)
}
/**
* Returns the total number of items in the data set held by the adapter.
*
* @return The total number of items in this adapter.
*/
override fun getItemCount(): Int = nodes.size
/**
* Called by RecyclerView to display the data at the specified position. This method should
* update the contents of the [ViewHolder.itemView] to reflect the item at the given
* position.
*
*
* Note that unlike [android.widget.ListView], RecyclerView will not call this method
* again if the position of the item changes in the data set unless the item itself is
* invalidated or the new position cannot be determined. For this reason, you should only
* use the `position` parameter while acquiring the related data item inside
* this method and should not keep a copy of it. If you need the position of an item later
* on (e.g. in a click listener), use [ViewHolder.getAdapterPosition] which will
* have the updated adapter position.
*
* Override [.onBindViewHolder] instead if Adapter can
* handle efficient partial bind.
*
* @param holder The ViewHolder which should be updated to represent the contents of the
* item at the given position in the data set.
* @param position The position of the item within the adapter's data set.
*/
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val n = nodes[position]
holder.nodeNameView.text = n.user?.longName ?: n.user?.id ?: "Unknown node"
}
private var nodes = arrayOf<NodeInfo>()
/// Called when our node DB changes
fun onNodesChanged(nodesIn: Collection<NodeInfo>) {
nodes = nodesIn.toTypedArray()
notifyDataSetChanged() // FIXME, this is super expensive and redraws all nodes
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.nodelist_fragment, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
nodeListView.adapter = nodesAdapter
nodeListView.layoutManager = LinearLayoutManager(requireContext())
model.nodeDB.nodes.observe(viewLifecycleOwner, Observer { it ->
nodesAdapter.onNodesChanged(it.values)
})
}
}
/*
@Composable
fun UsersContent() {
Column {

Wyświetl plik

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
style="@style/Widget.App.CardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="5dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/nodeNameView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:text="Unknown Username"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>

Wyświetl plik

@ -0,0 +1,19 @@
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/nodeListView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Wyświetl plik

@ -28,4 +28,5 @@
<item name="android:minHeight">48dp</item>
</style>
<style name="Widget.App.CardView" parent="Widget.MaterialComponents.CardView"></style>
</resources>