The Wearable UI Library includes the WearableRecyclerView class, which is a RecyclerView implementation for creating lists optimized for wearable devices. You can use this interface in your wearable app by creating a new WearableRecyclerView container.
Wearable recyclerview is used to create a circular layout and is an alternative to Boxlayout on Circular WearOS.
The most used public methods of this view are:
- setCircularScrollingGestureEnabled(boolean): For enabling/disabling circular touch scrolling for this view.
- setEdgeItemsCenteringEnabled(boolean): This method is used to indicate if the view should always align the first and last items with the vertical center of the screen. Below I will give an example with the Home screen of DCLM Watch
First the layout file and then the list item, the Adapter and the Activity
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.wear.widget.WearableRecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000"
android:scrollbars="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0.10"
android:scaleType="fitXY"
android:src="@drawable/nlogo"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
tools:ignore="ContentDescription" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/menu_container"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="androidx.core.content.ContextCompat"/>
<variable
name="data"
type="org.dclm.live.watch.MainScreen" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent">
<!-- -->
<!-- -->
<ImageView
android:id="@+id/menu_icon"
android:layout_width="35dp"
android:layout_height="35dp"
android:background="@android:color/transparent"
android:src="@{ContextCompat.getDrawable(context, data.drawable)}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/menu_item"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:text="@={data.heading}"
android:textColor="#fff"
android:textSize="13sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/menu_icon"
app:layout_constraintTop_toTopOf="@+id/menu_icon"
tools:text="swsssswxwx masxsag sxsxbvx" />
<TextView
android:id="@+id/menu_sub"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:text="@={data.category}"
android:textColor="#fff"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/menu_icon"
app:layout_constraintTop_toBottomOf="@+id/menu_item"
tools:text="swsssswxwx " />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
class MainActivity : WearableActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var adapter:MainAdapter
private lateinit var mainScreen: MutableList<MainScreen>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
mainScreen = ArrayList<MainScreen>()
mainScreen.add(MainScreen(1, R.drawable.nlogo2, getString(R.string.app_radio)))
mainScreen.add(MainScreen(2, R.drawable.baba, getString(R.string.recent_sermons)))
adapter = MainAdapter(mainScreen, this)
binding.recyclerView.isEdgeItemsCenteringEnabled = true
binding.recyclerView.layoutManager = WearableLinearLayoutManager(this)
binding.recyclerView.isCircularScrollingGestureEnabled = true;
binding.recyclerView.isEdgeItemsCenteringEnabled = true
binding.recyclerView.adapter = adapter
setAmbientEnabled()
}
override fun onExitAmbient() {
super.onExitAmbient()
}
override fun onEnterAmbient(ambientDetails: Bundle?) {
super.onEnterAmbient(ambientDetails)
}
}
data class MainScreen(var id: Int, var image: Int, var name: String)
class MainAdapter(val main: MutableList<MainScreen>, val context: Context): RecyclerView.Adapter<MainAdapter.Holder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
val binding = DataBindingUtil.inflate<ListItemBinding>(LayoutInflater.from(context), R.layout.list_item, parent, false)
return Holder(binding)
}
override fun getItemCount() = main.size
override fun onBindViewHolder(holder: Holder, position: Int) {
val main1 = main[position]
holder.binding.data = main1
holder.binding.root.setOnClickListener {
context.apply {
if (main1.id == 1){
startActivity(Intent())
} else{
startActivity(Intent())
}
}
}
}
class Holder(val binding: ActivityMainListBinding) : RecyclerView.ViewHolder(binding.root) {
}
}
If you need to implement custom child layout behavior on scroll, then you can use then you use this constructor WearableLinearLayoutManager(Context context, LayoutCallback layoutCallback)and then set your custom Layout Callback as the parameter for the layoutCallback. You can trust Android Magic by coping theirs as your custom LayoutCallback
/** How much should we scale the icon at most. */
private const val MAX_ICON_PROGRESS = 0.65f
class CustomScrollingLayoutCallback : WearableLinearLayoutManager.LayoutCallback() {
private var progressToCenter: Float = 0f
override fun onLayoutFinished(child: View, parent: RecyclerView) {
child.apply {
// Figure out % progress from top to bottom
val centerOffset = height.toFloat() / 2.0f / parent.height.toFloat()
val yRelativeToCenterOffset = y / parent.height + centerOffset
// Normalize for center
progressToCenter = Math.abs(0.5f - yRelativeToCenterOffset)
// Adjust to the maximum scale
progressToCenter = Math.min(progressToCenter, MAX_ICON_PROGRESS)
scaleX = 1 - progressToCenter
scaleY = 1 - progressToCenter
}
}
}
Top comments (1)
That's a good read, buddy!