Giter VIP home page Giter VIP logo

android-animated-theme-manager's Introduction

Android Animated Theme Manager Tweet

License Maven Central Generic badge Generic badge Generic badge CodeFactor Quality Gate Status

Create custom themes and change them dynamically with the ripple animation

✅ We are open to any new feature request, bug fix request, and pull request.

Demo

animation-ripple-android-theme

Features

  • support java and kotlin projects.
  • change theme without recreating activities and fragments.
  • support multi fragments apps.
  • ripple animation.
  • reverse animation.
  • changeable animation duration.
  • changeable animation position.
  • animation listener.
  • observe changes of themes for custom actions with Livedata.
  • easy to use, 5 or 7 tiny steps.
  • support any android APIs (animation works on API>20).


How to install? Maven Central

Add the following line to app-level build.gradle file, in dependencies scope:

dependencies {
    ...
    implementation "com.dolatkia:animated-theme-manager:1.1.4"
}

How to use?

1- Create an abstract class that inherits from AppTheme. In this class create abstract methods to return related color for all UI element that you want to change them on each theme. For example, if you want to change the background color, text colors and icon colors in your firstActivity, do the following:

interface MyAppTheme : AppTheme {
    fun firstActivityBackgroundColor(context: Context): Int
    fun firstActivityTextColor(context: Context): Int
    fun firstActivityIconColor(context: Context): Int
    // any other methods for other elements
}
java

interface MyAppTheme extends AppTheme {
    int firstActivityBackgroundColor(@NotNull Context context);
    int firstActivityTextColor(@NotNull Context context);
    int firstActivityIconColor(@NotNull Context context);
    // any other methods for other elements
}

2- For each theme that you want in your app, create a class that extends from the class that was created in step 1 (MyAppTheme), and implement methods with related colors or resources, for example, if you want to have 3 themes, you should create 3 class and implement methods:

class LightTheme : MyAppTheme {

    override fun id(): Int { // set unique iD for each theme 
        return 0
    }

    override fun firstActivityBackgroundColor(context: Context): Int {
        return ContextCompat.getColor(context, R.color.background_light)
    }

    override fun firstActivityTextColor(context: Context): Int {
        return ContextCompat.getColor(context, R.color.text_light)
    }
    
     override fun firstActivityIconColor(context: Context): Int {
        return ContextCompat.getColor(context, R.color.icon_light)
    }
    
    ...
}

class NightTheme : MyAppTheme {...}
class PinkTheme : MyAppTheme {...}
java

public class LightTheme implements MyAppTheme {
    public int id() { // set unique iD for each theme 
        return 0;
    }

    public int firstActivityBackgroundColor(@NotNull Context context) {
        return ContextCompat.getColor(context, R.color.background_light);
    }

    public int firstActivityTextColor(@NotNull Context context) {
        return ContextCompat.getColor(context,  R.color.text_light);
    }

    public int firstActivityIconColor(@NotNull Context context) {
        return ContextCompat.getColor(context, R.color.icon_light);
    }
    
    ...
}
    
public class NightTheme implements MyAppTheme {...}
public class PinkTheme implements MyAppTheme {...}

3- Extend your activity from ThemeActivity:

MainActivity : ThemeActivity() {
...
}
java

public class MainActivity implements ThemeActivity {
...
}

4- Implement ThemeActivity's 2 abstract methods:

// to sync ui with selected theme
override fun syncTheme(appTheme: AppTheme) {
    // change ui colors with new appThem here

    val myAppTheme = appTheme as MyAppTheme
    // set background color
    binder.root.setBackgroundColor(myAppTheme.firstActivityBackgroundColor(this))

    //set text color
    binder.text.setTextColor(myAppTheme.activityTextColor(this))
        
    // set icons color
    binder.share.setColorFilter(myAppTheme.firstActivityIconColor(this))
    binder.gift.setColorFilter(myAppTheme.firstActivityIconColor(this))        
    ...
}

// to save the theme for the next time, save it in onDestroy() (exp: in pref or DB) and return it here.
// it just used for the first time (first activity).
override fun getStartTheme(): AppTheme {
    return LightTheme()
}
java

// to sync ui with selected theme
@Override
public void syncTheme(@NotNull AppTheme appTheme) {
    // change ui colors with new appThem here

    MyAppTheme myAppTheme = (MyAppTheme) appTheme;

    // set background color
    binder.getRoot().setBackgroundColor(myAppTheme.activityBackgroundColor(this));

    //set text color
    binder.text.setTextColor(myAppTheme.activityTextColor(this));

    // set icons color
    binder.share.setColorFilter(myAppTheme.activityBackgroundColor(this));
    binder.gift.setColorFilter(myAppTheme.activityBackgroundColor(this));
}

// to get start theme
@NotNull
@Override
public AppTheme getStartTheme() {
    return new LightTheme();
}

5- Change theme with the ThemeManager.instance.changeTheme() method:

// set change theme click listener
binder.lightButton.setOnClickListener {
  ThemeManager.instance.changeTheme(LightTheme(), it)
}
java

binder.lightButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
      ThemeManager.Companion.getInstance().changeTheme(new LightTheme(), v, 600);
    }
});

The first argument is the selected theme.

The second argument is the view that animation starts from the center of it.

How to use in multi fragments app?

Repeat all previous 5 steps, and then:

6- Extend your fragments from ThemeFragment:

MyFragment : ThemeFragment() {
...
}
java

public class MyFragment implements ThemeFragment {
...
}

7- Implement ThemeFragment syncTheme abstract methods:

// to sync ui with selected theme
override fun syncTheme(appTheme: AppTheme) {
    // change ui colors with new appThem here
    ...
}
java

@Override
public void syncTheme(@NotNull AppTheme appTheme) {
    // change ui colors with new appThem here
    ...
}

Some other settings and customization:

✔️ reverse animation

If you want to use the reverse animation, call reverseChangeTheme() instead of changeTheme():

   binder.lightButton.setOnClickListener {
        ThemeManager.instance.reverseChangeTheme(LightTheme(), it)
   }

reverse ripple theme animation

✔️ change animation duration

If you want to change the animation duration, add your desired duration in milliseconds as the third argument of ThemeManager.instance.changeTheme(). The default value is 600:

   binder.lightButton.setOnClickListener {
        ThemeManager.instance.changeTheme(LightTheme(), it, 800)
   }

✔️ change animation center position

If you want to start animation somewhere other than the view that clicked, send a Coordinate object instead of a View in ThemeManager.instance.changeTheme()

   binder.lightButton.setOnClickListener {
          binder.nightButton.setOnClickListener {
            ThemeManager.instance.changeTheme(NightTheme(), Coordinate(10, 20)
        }
   }

where the Coordinate is:

 Coordinate(var x: Int, var y: Int) 

✔️ observe changes of themes yourself

If you want to observe changes of themes and do some custom action, you can use theme Livedata in any fragment or activity:

    ThemeManager.instance.getCurrentLiveTheme().observe(this) {
        Toast.makeText(this, "on Theme changed to ${it.id()}", Toast.LENGTH_SHORT).show()
    }

✔️ set animation listener

If you want to set an animation listener, use setThemeAnimationListener() method in your activity

     setThemeAnimationListener(MyThemeAnimationListener(this))

where the MyThemeAnimationListener is:

    class MyThemeAnimationListener(var context: Context) : ThemeAnimationListener{
        override fun onAnimationStart(animation: Animator) {
           Toast.makeText(context, "onAnimationStart", Toast.LENGTH_SHORT).show()
        }

        override fun onAnimationEnd(animation: Animator) {
            Toast.makeText(context, "onAnimationEnd", Toast.LENGTH_SHORT).show()
        }

        override fun onAnimationCancel(animation: Animator) {
            Toast.makeText(context, "onAnimationCancel", Toast.LENGTH_SHORT).show()
        }

        override fun onAnimationRepeat(animation: Animator) {
            Toast.makeText(context, "onAnimationRepeat", Toast.LENGTH_SHORT).show()
        }
    }

Stargazers

Stargazers repo roster for @imandolatkia/Android-Animated-Theme-Manager

Forkers

Forkers repo roster for @imandolatkia/Android-Animated-Theme-Manager

Quality gate

android-animated-theme-manager's People

Contributors

andreasroither avatar imandolatkia avatar kojofosu avatar lwj1994 avatar pelmenstar1 avatar wwdablu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

android-animated-theme-manager's Issues

save the theme

I don't understand what needs to be done to save the theme next time. How can we record in onDestroy. Can you show me a preview?

Clicking the button during the animation might cause button state confusion

Thank you for your invitation
I've been looking at your team's code and I feel pretty good about it.We are very happy to introduce this project into our project
However, I found a small flaw in the fact that clicking the button during the animation might cause button state confusion

 binder.button.setOnClickListener {
            isNight = if(isNight){
                ThemeManager.instance.reverseChangeTheme(LightTheme(), it)
                false
            }else{
                ThemeManager.instance.changeTheme(NightTheme(), it)
                true
            }
               ...
        }
fun changeTheme(
        newTheme: AppTheme,
        sourceCoordinate: Coordinate,
        animDuration: Long,
        isReverse: Boolean
    ) {
         ...

        if (frontFakeThemeImageView.visibility == View.VISIBLE ||
            behindFakeThemeImageView.visibility == View.VISIBLE ||
            isRunningChangeThemeAnimation()
        ) {
            return
        }
         ...
      }

I think the easy way to do that is to add a return value.Maybe not a good way to handle it

Hope your project will get better and better

Action bar?

Hi! How do I make it work on the action bar? GOOD JOB GUYS !!!

Cannot start anim on deAttachedView

java.lang.IllegalStateException: Cannot start this animator on a detached view!

When i click change theme button, all working good but when i open any acivity and go back then click, and crashed

Pass layout in activity constructor

⚠️ Is your feature request related to a problem? Please describe

I'm normally using a viewbinding library to simplify the process and prevent memory leaks.
ViewBindingPropertyDelegate

The library wants me to pass the layout in the activity constructor as described in the README.
This makes it impossible to use with this Theme-Manager.

💡 Describe the solution you'd like

It would be nice if this library were compatible with ViewBindingPropertyDelegate and the best option for this would be if it's possible to pass the layout in the constructor.

🤚 Do you want to develop this feature yourself?

  • Yes
  • No

RecyclerView

Hi @imandolatkia ! First of all I have to say that this library is AMAZING, this just save my life really!!

Could you explain how to implement this feature in a recycler? You said this a long time ago but I can´t se any related video :octocat:

HI @SudoDios,
It's a really good question.

1- You should synchronize the RecyclerView theme in Viewholders. I mean in the RecyclerView adapter and inonBindViewHolder method, with the use of ThemeManager.
2- After the theme is changed, if the fragment that contained RecyclerView was displaying, call notifyDataSetChanged() from its adapter.

I will add the sample in a week.

Thanks a lot !!! And again, very good job !!!

Activity theme

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.samprojre/com.example.samprojre.screens.main.MainActivity}: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
Currently, I am using Theme.Material3.Light.NoActionBar as a style for MainActivity and I didn't have that exception before when I extended MainActivity from AppCompatActivity

Cannot start animation on a detached view for a resumed Activity.

Although I easily fixed this issue, the solution should be included in the next update.

I'd give a bit of context on why this happened and how to recreate the problem.

I have a base class BaseActivity which extends ThemeActivity. All my Activity classes extend BaseActivity and so can override syncTheme() and getStartTheme().

Let's say I start from MainActivity which extends BaseActivity and in it's onCreate() it calls ThemeManager.init(activity, getStartTheme()). This happens from the ThemeActivity super class.

However when I navigate to another class say SecondActivity, this is what happens.

  • onStop() of MainActivity is called.
  • onCreate() of SecondActivity is called and this is where the ThemeManager instance is initialized again (from the super class ThemeActivity) and changes private activity variable from MainActivity to SecondActivity. This is fine as the current Context would be SecondActivity.

But when I navigate back to MainActivity, this is what happens.

  • onStop() for SecondActivity is called.
  • onRestart() for MainActivity is called.
    Since the MainActivity is not destroyed and remained on the heap, it just stopped and restarted. It's onCreate() was not called and that means the activity variable in the ThemeManager instance that was reinstantiated when SecondActivity was navigated to still has the private activity variable as the SecondActivity instance (which should have been destroyed when navigated back up). This is a resource leak.

And so whenever I try to change theme in MainActivity, I get a "Cannot run animation on a detached View" error from the ViewAnimator.

I fixed this error by reinstantiating ThemeManager by calling ThemeManager.init(activity, getStartTheme()) in the onRestart() of MainActivity and that fixed my issue.

So I feel onRestart() should be overriden in ThemeActivity and ThemeManager should reinstantiated on that callback.

I did a debug on my code when carrying out the above scenario and found that issue out.

Java How to use? something missing?

I try to add this using java. but suddenly i saw "binder.root." what is this? How can i syncTheme in java? i think this is important but you missing explanation???

java.lang.ClassCastException: android.view.ViewRootImpl cannot be cast to android.view.View

🐛 Describe the bug
The issue arises in the ThemeManager class within the application. Specifically, there seems to be an error related to class casting in the getRelativeLeft and getRelativeTop methods.

⚠️ Current behavior
When certain conditions are met, the application crashes with a ClassCastException in the ThemeManager class.

Error:

java.lang.ClassCastException: android.view.ViewRootImpl cannot be cast to android.view.View
at com.dolatkia.animatedThemeManager.ThemeManager.getRelativeLeft(ThemeManager.kt:133)
at com.dolatkia.animatedThemeManager.ThemeManager.getRelativeLeft(ThemeManager.kt:133)
at com.dolatkia.animatedThemeManager.ThemeManager.getRelativeLeft(ThemeManager.kt:133)
at com.dolatkia.animatedThemeManager.ThemeManager.getRelativeLeft(ThemeManager.kt:133)
at com.dolatkia.animatedThemeManager.ThemeManager.getRelativeLeft(ThemeManager.kt:133)
at com.dolatkia.animatedThemeManager.ThemeManager.getRelativeLeft(ThemeManager.kt:133)
at com.dolatkia.animatedThemeManager.ThemeManager.getRelativeLeft(ThemeManager.kt:133)
at com.dolatkia.animatedThemeManager.ThemeManager.getRelativeLeft(ThemeManager.kt:133)
at com.dolatkia.animatedThemeManager.ThemeManager.getRelativeLeft(ThemeManager.kt:133)
at com.dolatkia.animatedThemeManager.ThemeManager.getRelativeLeft(ThemeManager.kt:133)
at com.dolatkia.animatedThemeManager.ThemeManager.getRelativeLeft(ThemeManager.kt:133)
at com.dolatkia.animatedThemeManager.ThemeManager.getRelativeLeft(ThemeManager.kt:133)
at com.dolatkia.animatedThemeManager.ThemeManager.getViewCoordinates(ThemeManager.kt:127)
at com.dolatkia.animatedThemeManager.ThemeManager.changeTheme(ThemeManager.kt:48)
at .Fragments.Profile.FgProfileSettings.lambda$onViewCreated$3$....-Fragments-Profile-FgProfileSettings(FgProfileSettings.java:151)
at .Fragments.Profile.FgProfileSettings$$ExternalSyntheticLambda16.onCheckedChanged(D8$$SyntheticClass:0)
at android.widget.CompoundButton.setChecked(CompoundButton.java:222)
at androidx.appcompat.widget.SwitchCompat.setChecked(SwitchCompat.java:1179)
at androidx.appcompat.widget.SwitchCompat.toggle(SwitchCompat.java:1174)
at android.widget.CompoundButton.performClick(CompoundButton.java:144)
at android.view.View.performClickInternal(View.java:7519)
at android.view.View.-$$Nest$mperformClickInternal(Unknown Source:0)
at android.view.View$PerformClick.run(View.java:29476)
at android.os.Handler.handleCallback(Handler.java:942)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7918)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)

Fragment:

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

import androidx.annotation.NonNull;
import androidx.appcompat.widget.SwitchCompat;

import com.dolatkia.animatedThemeManager.AppTheme;
import com.dolatkia.animatedThemeManager.ThemeFragment;
import com.dolatkia.animatedThemeManager.ThemeManager;

public class FgProfileSettings extends ThemeFragment {
    private SwitchCompat sw_theme;
    private CmpTextView tv_theme;
    private RelativeLayout rl_theme;
    private View v_theme;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View this_view = inflater.inflate(R.layout.fg_profile_settings, container, false);

        rl_theme = this_view.findViewById(R.id.rl_theme);
        tv_theme = this_view.findViewById(R.id.tv_theme);
        v_theme = this_view.findViewById(R.id.v_theme);

        return this_view;
    }


    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        sw_theme.setOnCheckedChangeListener((buttonView, isChecked) -> {
            if(isChecked) {
                ThemeManager.Companion.getInstance().changeTheme(new ThemesDay(), v_theme, 600);
            } else {
                ThemeManager.Companion.getInstance().changeTheme(new ThemesNight(), v_theme, 600);
            }
        });
    }

    @Override
    public void onResume() {
        super.onResume();
    }

    @Override
    public void syncTheme(@NonNull AppTheme appTheme) {
        ITheme myAppTheme = (ITheme) appTheme;
        tv_theme.setTextColor(myAppTheme.setColor(requireContext(), EnumColor.BLACK));
    }
}

Interface:

public interface ITheme extends AppTheme {
    int setColor(@NotNull Context context, EnumColor color);
}

ThemeDay:

public class ThemesDay implements ITheme {
    public int id() { // set unique iD for each theme
        return 0;
    }

    @Override
    public int setColor(@NotNull Context context, EnumColor color) {
        return Color.parseColor(getColor(color));
    }

    private String getColor(EnumColor color){
        switch (color){
            case WHITE:
                return "#FFFFFF";
            default:
                return "#FFFFFF";
        }
    }
}

ThemeNight

public class ThemesNight implements ITheme {
    public int id() { // set unique iD for each theme
        return 0;
    }

    @Override
    public int setColor(@NotNull Context context, EnumColor color) {
        return Color.parseColor(getColor(color));
    }


    private String getColor(EnumColor color){
        switch (color){
            case WHITE:
                return "#181F2A";
            default:
                return "#181F2A";
        }
    }
}

BottomSheetBehavior

I create a bottomsheetbehavior and add inside a recyclerview contains theme list.
But i click item recyclerview to change theme ThemeManager animated theme on over bottomsheet and bottomsheet has Gone.

The specified child already has a parent exception at setContentView

My code works fine if my activity extends from AppCompatActivity, but I got this exception when extends ThemeActivity

Process: com.example.todoapp, PID: 5708
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.todoapp/com.example.todoapp.MainActivity}: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3449)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
     Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
        at android.view.ViewGroup.addViewInner(ViewGroup.java:5235)
        at android.view.ViewGroup.addView(ViewGroup.java:5064)
        at android.view.ViewGroup.addView(ViewGroup.java:5004)
        at android.view.ViewGroup.addView(ViewGroup.java:4976)
        at com.dolatkia.animatedThemeManager.ThemeActivity.setContentView(ThemeActivity.kt:59)
        at com.dolatkia.animatedThemeManager.ThemeActivity.setContentView(ThemeActivity.kt:54)
        at com.example.todoapp.MainActivity.onCreate(MainActivity.kt:27)
        at android.app.Activity.performCreate(Activity.java:8000)
        at android.app.Activity.performCreate(Activity.java:7984)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:223) 
        at android.app.ActivityThread.main(ActivityThread.java:7656) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 

My MainActivity.kt

package com.example.todoapp

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.drawerlayout.widget.DrawerLayout
import com.dolatkia.animatedThemeManager.AppTheme
import com.dolatkia.animatedThemeManager.ThemeActivity
import com.dolatkia.animatedThemeManager.ThemeManager
import com.google.android.material.appbar.MaterialToolbar
import com.google.android.material.navigation.NavigationView

class MainActivity : ThemeActivity() {

    private lateinit var drawerLayout: DrawerLayout
    private lateinit var topAppBar: MaterialToolbar
    private lateinit var navigationView: NavigationView

    override fun getStartTheme(): AppTheme {
        return LightTheme()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main)             // I GOT EXCEPTION HERE

        // Views
        drawerLayout = findViewById(R.id.drawer)
        topAppBar = findViewById(R.id.topAppBar)
        navigationView = findViewById(R.id.navigation_view)

        supportFragmentManager.beginTransaction().replace(R.id.fragment_container, MainFragment()).commit()

        topAppBar.setNavigationOnClickListener {
            drawerLayout.open()
        }

        navigationView.setNavigationItemSelectedListener { menuItem ->
            if (menuItem.isChecked) {
                false
            } else {
                // Handle menu item selected
                when (menuItem.itemId) {
                    R.id.nav_main -> supportFragmentManager.beginTransaction().replace(R.id.fragment_container, MainFragment()).commit()
                    R.id.nav_about -> supportFragmentManager.beginTransaction().replace(R.id.fragment_container, AboutFragment()).commit()
                }

                menuItem.isChecked = true
                drawerLayout.close()
                false
            }
        }
    }

    override fun syncTheme(appTheme: AppTheme) {
        val myAppTheme = appTheme as MyAppTheme

        drawerLayout.rootView.setBackgroundColor(myAppTheme.firstActivityBackgroundColor(this))
    }
}

My activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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:id="@+id/drawer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true">

        <com.google.android.material.appbar.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            style="@style/Widget.MaterialComponents.ActionBar.PrimarySurface"
            android:fitsSystemWindows="true">
            
            <com.google.android.material.appbar.MaterialToolbar
                android:id="@+id/topAppBar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:title="Main"
                app:navigationIcon="@drawable/ic_baseline_menu_24"
                style="@style/Widget.MaterialComponents.ActionBar.PrimarySurface"
                android:background="@android:color/transparent"
                android:elevation="0dp" />


        </com.google.android.material.appbar.AppBarLayout>

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/fragment_container"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    </androidx.coordinatorlayout.widget.CoordinatorLayout>

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/navigation_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:menu="@menu/navigation_drawer" />


</androidx.drawerlayout.widget.DrawerLayout>

Can you help me get through this. Anyway thank you for an amazing library (sorry for my bad english)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.