Search code examples
androidkotlinandroid-tablayout

How to display the Tabs from the TabLayout one above the other on left side of the screen in android?


So, I am trying to display three Tabs [Easy, Medium, Hard] in TabLayout and I want these Tabs to get displayed one above the other. Currently I am getting result like this enter image description here

So, as you can see, these tabs are one next to other instead of one below the other.Following is code of my XML file

<RelativeLayout
    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"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent">
    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_alignParentStart="true"
        android:layout_gravity="start"
        app:tabGravity="fill"
        app:tabMode="scrollable" />

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="120dp"
        android:background="@drawable/flash_tablebar"
        android:elevation="4dp"
        android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
        android:layout_alignParentTop="true">

        <ImageView
            android:id="@+id/back_icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:src="@drawable/ic_arrow_back" />

        <RelativeLayout
            android:layout_marginLeft="20dp"
            android:id="@+id/relativeFlashcard"
            android:layout_width="wrap_content"
            android:layout_height="100dp"
            android:layout_toRightOf="@id/back_icon"
            >
        <TextView
        android:id="@+id/title_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
            android:textStyle="bold"
            android:layout_marginStart="30dp"
        android:text="Flashcards"
        android:textSize="40sp"
        android:textColor="#FFF" />
            <TextView
                android:id="@+id/subtext_flash"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textStyle="bold"
                android:layout_below="@id/title_text"
                android:layout_marginStart="30dp"
                android:text="Pick a set to practice"
                android:textSize="20sp"
                android:textColor="#FFF" />
        </RelativeLayout>
    </androidx.appcompat.widget.Toolbar>
        <!-- ViewPager -->
        <androidx.viewpager.widget.ViewPager
            android:id="@+id/viewPager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:contentDescription="" />

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerViewFlashcards"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="70dp"
            android:layout_marginEnd="5dp"
            android:layout_below="@id/toolbar"
            android:layout_alignParentBottom="true"
            android:scrollbars="vertical">
        </androidx.recyclerview.widget.RecyclerView>
</RelativeLayout>

And following is the code of my Fragment class

import androidx.viewpager.widget.ViewPager
import com.example.visuallithuanian.R
import com.google.android.material.tabs.TabLayout
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter
import com.example.visuallithuanian.EasyFragment
import com.example.visuallithuanian.HardFragment
import com.example.visuallithuanian.MediumFragment
import dagger.hilt.android.AndroidEntryPoint


@AndroidEntryPoint
class FlashCards : Fragment() {

    private lateinit var tabLayout: TabLayout
    private lateinit var viewPager: ViewPager

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_flash_cards,
container, false)

        // Initialize views
        tabLayout = view.findViewById(R.id.tabLayout)
        viewPager = view.findViewById(R.id.viewPager)

        // Set up the ViewPager and TabLayout
        val adapter = FlashCardsPagerAdapter(childFragmentManager)
        viewPager.adapter = adapter
        tabLayout.setupWithViewPager(viewPager)

        return view
    }

    private inner class FlashCardsPagerAdapter(fm: FragmentManager) :
FragmentPagerAdapter(fm) {

        override fun getCount(): Int {
            return 3 // Number of tabs (Easy, Medium, Hard)
        }

        override fun getItem(position: Int): Fragment {
            return when (position) {
                0 -> EasyFragment()
                1 -> MediumFragment()
                2 -> HardFragment()
                else -> throw IllegalArgumentException("Invalid position")
            }
        }

        override fun getPageTitle(position: Int): CharSequence? {
            return when (position) {
                0 -> "Easy"
                1 -> "Medium"
                2 -> "Hard"
                else -> null
            }
        }
    }
}

So, I just want these Tabs to be one above the other like first Easy , then medium and then Hard so I can traverse the respective Fragments. I want my Tabs to look like this enter image description here


Solution

  • Since API11, we can rotate views by calling setRotation() or by setting the XML attribute android:rotation. You could try to attach this attribute to the views to achieve the desired result. To rotate a view by 90 degress clockwise, just set android:rotation="90".

    Use below layout to get the idea. Note that I am not able to test it right now, but this could provide you some direction. We first rotate the whole Tablayout cw, and then we rotate back the single TabItems.

    <FrameLayout
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:rotation="90"
        android:layout_gravity="center_vertical">
    
        <com.google.android.material.tabs.TabLayout
            android:id="@+id/tabLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            app:tabIndicatorHeight="4dp"
            app:tabInlineLabel="true"
            app:tabIndicatorFullWidth="false"
            android:background="@color/white" >
    
            <com.google.android.material.tabs.TabItem
                android:id="@+id/tabItemEasy"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:rotation="-90"
                android:text="Easy" />
    
            <com.google.android.material.tabs.TabItem
                android:id="@+id/tabItemMedium"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:rotation="-90"
                android:text="Medium" />
    
            <com.google.android.material.tabs.TabItem
                android:id="@+id/tabItemHard"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:rotation="-90"
                android:text="Hard" />
    
        </com.google.android.material.tabs.TabLayout>
    </FrameLayout>
    

    See also this StackOverflow question for reference.

    Please however note that this design approach in general does not conform to the Google Material Design Guidelines, so you might want to overthink if there are alternatives more suitable.