Android selector with fade in / fade out duration initially invisible

前端 未结 4 1510
无人及你
无人及你 2021-02-08 01:18

I\'m trying to achieve that an icon in ActionBar will not change states discretely, but by fading animation. When I add android:enterFadeDuration and android:

相关标签:
4条回答
  • 2021-02-08 01:49

    Use android:enterFadeDuration="@android:integer/config_mediumAnimTime" and android:exitFadeDuration="@android:integer/config_mediumAnimTime".

    0 讨论(0)
  • 2021-02-08 01:50

    This seems to be a bug that happens on specific Android versions. You can turn off the android:enterFadeDuration programmatically in Java code, by accessing the Selector with a StateListDrawable:

    // Disable android:enterFadeDuration/exitFadeDuration on Android 4.2 only
    if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR1) {
        StateListDrawable stateListDrawable =
                (StateListDrawable) animatedButton.getBackground();
        stateListDrawable.setEnterFadeDuration(0);
        stateListDrawable.setExitFadeDuration(0);
    }
    
    0 讨论(0)
  • 2021-02-08 01:53

    I had a similar problem, with my code looking like this:

    <selector xmlns:android="http://schemas.android.com/apk/res/android" 
              android:enterFadeDuration="@android:integer/config_mediumAnimTime"
              android:exitFadeDuration="@android:integer/config_mediumAnimTime" >
        <item android:state_pressed="true" android:drawable="@color/pressed" />
        <item android:drawable="@color/default" />
    </selector>
    

    At first, I found a hint to get rid of enterFadeDuration and only use exitFadeDuration. That solved the problem with initial invisibility, but the view still faded into invisibility during the first interraction.

    Then, I modified my structure as follows:

    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@color/default" />
        <item>
            <selector android:enterFadeDuration="@android:integer/config_mediumAnimTime"
                      android:exitFadeDuration="@android:integer/config_mediumAnimTime" >
                <item android:state_pressed="true" android:drawable="@color/pressed" />
            </selector>
        </item>
    </layer-list>
    

    Basically, I just pushed the default drawable out of the selector. It's a workaround and it also works for selectors with multiple states, but has some notable limitations:

    • The default drawable is always visible as a bottom layer. It works for opaque colors, but transparency may cause undesirable results.
    • If the view starts in one of the states tested by selector, in still displays as default, because the selector still starts as invisible.

    It might not be applicable to the original problem, but it's something to consider for overcoming this behaviour of selectors.

    0 讨论(0)
  • 2021-02-08 01:57

    My problem was similar as well, the issue was that after setting a background drawable on my view, it was in the wrong state (sometimes it even mixed the stroke and solid of two states...). This was only before the first interaction, like receiving focus or changing enabled state.

    I've found that if you call jumpToCurrentState() on the drawable (which has the fade duration properties) after setting it on the view, it will be set on the correct state, and you can keep on using the enter / exit fade duration properties. Here's how I did it:

    val stateList = (darkBackground as? RippleDrawable)?.findDrawableByLayerId(android.R.id.background) as? StateListDrawable
    background = darkBackground
    stateList?.jumpToCurrentState()
    

    In this example I had a ripple drawable which contained the selector which had the fade properties (I had to add an ID to the selector so I could look it up using the ID).

    0 讨论(0)
提交回复
热议问题