javaandroidwear-osandroid-wear-2.0

WearableRecyclerView Android Wear OS


I'm trying to create a menu similar to the default Wear OS one within my app: Wear OS menu

Various other methods are now deprecated, and unfortunately the Android documentation https://developer.android.com/training/wearables/ui/lists seems very incomplete.

I cannot find any good examples to follow so does anyone have a WearableRecyclerView example that could set menu items and icons such as this, and capture the click events?

Thanks


Solution

  • I figured it out myself after a few days of trying. It might not be the best but at least it's working. I used vector icons created by Android Studio in the res/drawable directory. For anyone else looking for a solid example:

    main_menu.xml:

    <android.support.wear.widget.WearableRecyclerView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/main_menu_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical" />
    

    main_menu_item.xml:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/menu_container"
        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"
        android:paddingBottom="5dp"
        android:paddingTop="5dp">
    
        <ImageView
            android:id="@+id/menu_icon"
            android:layout_width="35dp"
            android:layout_height="35dp"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_centerVertical="true"
            tools:ignore="HardcodedText" />
    
        <TextView
            android:id="@+id/menu_item"
            android:layout_width="wrap_content"
            android:layout_height="35dp"
            android:layout_centerVertical="true"
            android:layout_toEndOf="@+id/menu_icon"
            android:layout_toRightOf="@+id/menu_icon"
            android:text="Menu Item"
            android:textColor="#000000"
            android:textSize="24sp"
            tools:ignore="HardcodedText" />
    </RelativeLayout>
    

    MainMenuActivity.java:

    public class MainMenuActivity extends WearableActivity {
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_menu);
        WearableRecyclerView recyclerView = findViewById(R.id.main_menu_view);
        recyclerView.setHasFixedSize(true);
        recyclerView.setEdgeItemsCenteringEnabled(true);
        recyclerView.setLayoutManager(new WearableLinearLayoutManager(this));
    
        ArrayList<MenuItem> menuItems = new ArrayList<>();
        menuItems.add(new MenuItem(R.drawable.icon_1, "Item 1"));
        menuItems.add(new MenuItem(R.drawable.icon_2, "Item 2"));
        menuItems.add(new MenuItem(R.drawable.icon_3, "Item 3"));
        menuItems.add(new MenuItem(R.drawable.icon_4, "Item 4"));
    
        recyclerView.setAdapter(new MainMenuAdapter(this, menuItems, new MainMenuAdapter.AdapterCallback() {
            @Override
            public void onItemClicked(final Integer menuPosition) {
                switch (menuPosition){
                    case 0:  action_1(); break;
                    case 1:  action_2(); break;
                    case 2:  action_3(); break;
                    case 3:  action_4(); break;
                    default : cancelMenu();
                }
            }
        }));
    }
    

    MainMenuAdapter.java:

    public class MainMenuAdapter extends RecyclerView.Adapter<MainMenuAdapter.RecyclerViewHolder> {
    
        private ArrayList<MenuItem> dataSource = new ArrayList<MenuItem>();
        public interface AdapterCallback{
            void onItemClicked(Integer menuPosition);
        }
        private AdapterCallback callback;
    
        private String drawableIcon;
        private Context context;
    
    
        public MainMenuAdapter(Context context, ArrayList<MenuItem> dataArgs, AdapterCallback callback){
            this.context = context;
            this.dataSource = dataArgs;
            this.callback = callback;
        }
    
        @Override
        public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view =LayoutInflater.from(parent.getContext()).inflate(R.layout.main_menu_item,parent,false);
    
            RecyclerViewHolder recyclerViewHolder = new RecyclerViewHolder(view);
    
            return recyclerViewHolder;
        }
    
        public static class RecyclerViewHolder extends RecyclerView.ViewHolder
        {
            RelativeLayout menuContainer;
            TextView menuItem;
            ImageView menuIcon;
    
            public RecyclerViewHolder(View view) {
                super(view);
                menuContainer = view.findViewById(R.id.menu_container);
                menuItem = view.findViewById(R.id.menu_item);
                menuIcon = view.findViewById(R.id.menu_icon);
            }
        }
    
        @Override
        public void onBindViewHolder(RecyclerViewHolder holder, final int position) {
            MenuItem data_provider = dataSource.get(position);
    
            holder.menuItem.setText(data_provider.getText());
            holder.menuIcon.setImageResource(data_provider.getImage());
            holder.menuContainer.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(final View v) {
    
                    if(callback != null) {
                        callback.onItemClicked(position);
                    }
                }
            });
        }
    
        @Override
        public int getItemCount() {
            return dataSource.size();
        }
    }
    
    class MenuItem {
        private String text;
        private int image;
    
        public MenuItem(int image, String text) {
            this.image = image;
            this.text = text;
        }
    
        public String getText() {
            return text;
        }
    
        public int getImage() {
            return image;
        }
    }