Android development

A few ways to avoid a splash screen when switching themes


While there is no change in the activity’s setTheme, there is a need to call the activity’s setTheme (see “setTheme”) to make the activity’s setTheme (see “setTheme”) functional. There is a flash screen after the activity calls the Concrete method

The topic of this article today is how to avoid the setTheme that calls the concept flash screen after switching the theme. The article on how to change the theme by changing the theme can be read if you haven’t already or do a search for it

recreate

Effect of implementation

1. Property animation implementation

Use the property animation in conjunction with the ArgbEvaluator class to animate gradients for all views that need to change colors

Attribute animation

The disadvantages of this approach are as follows:

  • Any View that needs to have a color change you’re going to have to set the ID and get its object by findViewById, and you’re going to have to add a lot of code to it, and you know how painful it is to set the ID to findViewById.
  • Each attR color setting requires a property animation, which increases the amount of code
  • RecyclerView or ListView and how to change the color of some special controls (such as MD-style Button, RadioButton Switch and other controls that cannot change the color by setting background)

So let’s see how we do that in code

Get the attrs color set in the theme using the following method

/ * * * @paramTheme Requires the theme * of the attrs color @paramId Id of the ATTRs color to be obtained @return color
 */
public static int getColorFromTheme(Resources.Theme theme, @AttrRes int id) 
    {
        TypedValue typedValue = new TypedValue();
        theme.resolveAttribute(id, typedValue, true);
        return typedValue.data;
    }Copy the code

All we need to do is get the current color and the changed Theme color and use getTheme in the activity to get the Theme object

int startColorPrimary = ThemeUtil.getColorFromTheme(getTheme()R.attr.colorPrimary);
setTheme(R.style.NightTheme);
int endColorPrimary = ThemeUtil.getColorFromTheme(getTheme(),R.attr.colorPrimary);Copy the code

The next step is to set up a property animation with ArgbEvaluator for color gradient

ValueAnimator animator = ValueAnimator
                .ofObject(new ArgbEvaluator(), 
                startColorPrimary, endColorPrimary)
                .setDuration(300);

animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int color = (int) animation.getAnimatedValue();
                // Set the background color control (Toolbar, background Layout, etc.)
                mView.setBackgroundColor(color);
                //TextView font color
                mTextView.setTextColor(color);
                / / ImageView Tint
                mImageView.setColorFilter(color);
                // Set the status bar or navigation bar color (API>=21)getWindow().setStatusBarColor(color); getWindow().setNavigationBarColor(color); }}); animator.start();Copy the code

The switching effect is achieved by manipulating all the controls that need to change colors

The following is about RecyclerView and MD style Button RadioButton Switch more color change method (which RadioButton Switch implementation is not perfect if you know welcome to add)

Change the color of the Item currently displayed on the screen by obtaining RecyclerView

int childCount = mRecyclerView.getChildCount();
for (int childIndex = 0; childIndex < childCount; childIndex++) {
                ViewGroup childView = (ViewGroup) mRecyclerView.getChildAt(childIndex);
                // childView is the outermost view of each item in RecyclerView
                // We can get the control of each item by id
                View mView = childView.findViewById(R.id.item_view);
                // Set the property animation to change the color of the view
                ....
            }Copy the code

Void RecyclerView cache Pool Item The idea here is to get the RecycleBin object in the AbsListView class by reflection and then use reflection again to call the Clear method which picks up the night mode implementation of the zhizhihouji and Simple book

Class<RecyclerView> recyclerViewClass = RecyclerView.class;
            try {
                Field declaredField = recyclerViewClass.getDeclaredField("mRecycler");
                declaredField.setAccessible(true);
                Method declaredMethod = Class.forName(RecyclerView.Recycler.class.getName()).getDeclaredMethod("clear", (Class<? >[]) new Class[0]);
                declaredMethod.setAccessible(true);
                declaredMethod.invoke(declaredField.get(mRecyclerView), new Object[0]);
                RecyclerView.RecycledViewPool recycledViewPool = mRecyclerView.getRecycledViewPool(a);
                recycledViewPool.clear(a);
            } catch (Exception e) {
                e.printStackTrace(a);
            }Copy the code

Button RadioButton Switch Progressbar changes its color by setting Tint

//Switch(not perfect, will change the color of thumb to grey when not selected)
mSwitch.setThumbTintList(ColorStateList.valueOf(color));
//RadioButton(not perfect, will change the color of the unselected circle to grey by default)
CompoundButtonCompat.setButtonTintList(mRadioButton, ColorStateList.valueOf(color));
//Button Progressbar
ViewCompat.setBackgroundTintList(mBotton, ColorStateList.valueOf(color));Copy the code

The disadvantages of animated properties are obvious, the more complex the layout is, the more difficult it is to write and the amount of code, the final effect is not very perfect, the difficulty is how to change the color of the special control, here interested readers can study, the following is a simpler way


2. StartActivity implementation

This approach is similar to the concept of calling Concrete in that flashscreens can be avoided by creating an identical activity and adding an animation

startActivity

The difficulty with this method is:

  • How do I restore the state of the previous activity so that the user does not notice the change in the control

So here’s the code

Create a new same activity and set the fade in and out animation to end the current activity

startActivity(new Intent(this, MainActivity.class));
overridePendingTransition(R.anim.start_anim, R.anim.out_anim);
finish();Copy the code

So you start the intent that you create for the activity to pass data from the old interface like EditText input and RecyclerView data and slide distance

Here is a list of save RecyclerView sliding distance specific need to save data need to be written according to the content of the interface

// Get the sliding distance of RecyclerView
// Call getScrollY to get the data 0, also can listen to the slide event to save the slide distance
private int getScrollYDistance() {
        LinearLayoutManager layoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
        int position = layoutManager.findFirstVisibleItemPosition();
        View firstVisibleChildView = layoutManager.findViewByPosition(position);
        int itemHeight = firstVisibleChildView.getHeight();
        return (position) * itemHeight - firstVisibleChildView.getTop();
    }

// Pass data to a new activity with an intent
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("scrollY",getcrollYDistance());

Restore the data in the activity's onCreate method
// The RecyclerView setScrollBy method can only take effect after the view is measured
mRecyclerView.post(new Runnable() {
            @Override
            public void run() {
              mRecyclerView.scrollBy(0,getIntent().getIntExtra("scrollY".0)); }});Copy the code

The difficulty is how to transfer and save the list data in the network request. Passing too much data in the intent can cause a crash because it is a new activity created, and the result is perfect


conclusion

This is my first time to write a technical summary, there must be a lot of problems, I hope the friends need to be able to learn from the kind of new knowledge, finally attached to the Demo link github.com/Misutesu/Ni… (There seems to be something wrong with the selected status of RadioButton in this Demo when selecting switching mode. I haven’t found the reason yet. If you find it, please leave a message and tell me.)

Thank you for reading