Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[1523] Add support for default styles to LottieAnimationView #1524

Merged
merged 1 commit into from
Mar 2, 2020

Conversation

ataulm
Copy link
Contributor

@ataulm ataulm commented Feb 27, 2020

Fixes #1523, with an enhancement.

Issue description

The issue was that the defStyleAttr would not be respected - the following class would compile, but R.attr.heartViewStyle would be ignored:

class HeartView(context: Context, attrs: AttributeSet)
    : LottieAnimationView(context, attrs, R.attr.heartViewStyle)

This meant that if we had a style:

<style name="Widget.LottieSample.HeartView">
    <item name="lottie_autoPlay">true</item>
    <item name="lottie_loop">true</item>
    <item name="lottie_url">https://raw.githubusercontent.com/airbnb/lottie-android/master/LottieSample/src/main/res/raw/heart.json</item>
</style>

we'd need to apply it explicitly in the layout each time we used it to a LottieAnimationView (or HeartView, but at this stage, there's no need for HeartView to exist - it doesn't do anything):

<com.airbnb.lottie.LottieAnimationView
    style="@style/Widget.LottieSample.HeartView"
    android:layout_width="256dp"
    android:layout_height="256dp"
    android:layout_gravity="center" />

Solving the issue

After delegating defStyleAttr to the init function, and passing it to the context.obtainedStyledAttributes call, we're able to do this (note, there's no explicit style on this view):

<com.airbnb.lottie.samples.HeartView
    android:layout_width="256dp"
    android:layout_height="256dp"
    android:layout_gravity="center" />

as long as we set the heartViewStyle attribute in our application theme:

<style name="Theme.LottieSample" parent="Theme.AppCompat.Light.NoActionBar">
    ...
    <item name="heartViewStyle">@style/Widget.LottieSample.HeartView</item>
</style>

<style name="Widget.LottieSample.HeartView">
    <item name="lottie_autoPlay">true</item>
    <item name="lottie_loop">true</item>
    <item name="lottie_url">https://raw.githubusercontent.com/airbnb/lottie-android/master/LottieSample/src/main/res/raw/heart.json</item>
</style>
...

so every time we use HeartView, it'll use the correct style by default, across the app.

Enhancing our solution

The addition that isn't covered in the original issue is adding a default style attribute for LottieAnimationView in the library, R.attr.lottieAnimationViewStyle.

This allows us to set default Lottie attributes across our app, for example the autoPlay and loop properties:

<style name="Theme.LottieSample" parent="Theme.AppCompat.Light.NoActionBar">
    ...
    <item name="lottieAnimationViewStyle">@style/Widget.LottieSample.LottieAnimationView</item>
</style>

<style name="Widget.LottieSample.LottieAnimationView" parent="android:Widget">
    <item name="lottie_autoPlay">true</item>
    <item name="lottie_loop">true</item>
</style>

such that in our layouts, we'd only need to specify the url, and we wouldn't need to use a custom view to do it:

<com.airbnb.lottie.LottieAnimationView
    android:layout_width="256dp"
    android:layout_height="256dp"
    android:layout_gravity="center"
    app:lottie_url="https://raw.githubusercontent.com/airbnb/lottie-android/master/LottieSample/src/main/res/raw/lottielogo.json" />

<com.airbnb.lottie.LottieAnimationView
    android:layout_width="256dp"
    android:layout_height="256dp"
    android:layout_gravity="center"
    app:lottie_url="https://raw.githubusercontent.com/airbnb/lottie-android/master/LottieSample/src/main/res/raw/heart.json" />

We can still override these properties in our layouts, if the default isn't suitable for all cases. And this is what the above looks like:

lottie

This solution works alongside any custom views too - so if you want a HeartView (or a LoadingIndicatorView) where you don't have to specify any Lottie attributes - but most of the time, it's ok to use the vanilla LottieAnimationView because you're not reusing that particular icon, you can (the GIF looks the same with this layout and theme setup):

<com.airbnb.lottie.LottieAnimationView
    android:layout_width="256dp"
    android:layout_height="256dp"
    android:layout_gravity="center"
    app:lottie_url="https://raw.githubusercontent.com/airbnb/lottie-android/master/LottieSample/src/main/res/raw/lottielogo.json" />

<com.airbnb.lottie.samples.HeartView
    android:layout_width="256dp"
    android:layout_height="256dp"
    android:layout_gravity="center" />

where we've refactored Widget.LottieSample.Heart to extend from our default Widget.LottieSample.LottieAnimationView style, so that it also has the autoPlay and loop properties:

<style name="Theme.LottieSample" parent="Theme.AppCompat.Light.NoActionBar">
    ...
    <item name="lottieAnimationViewStyle">@style/Widget.LottieSample.LottieAnimationView</item>
    <item name="heartViewStyle">@style/Widget.LottieSample.LottieAnimationView.HeartView</item>
</style>

<style name="Widget.LottieSample.LottieAnimationView" parent="android:Widget">
    <item name="lottie_autoPlay">true</item>
    <item name="lottie_loop">true</item>
</style>

<style name="Widget.LottieSample.LottieAnimationView.HeartView">
    <!-- inherits autoPlay and loop from the parent style -->
    <item name="lottie_url">https://raw.githubusercontent.com/airbnb/lottie-android/master/LottieSample/src/main/res/raw/heart.json</item>
</style>

@@ -122,21 +123,21 @@ public void onResult(Throwable result) {

public LottieAnimationView(Context context) {
super(context);
init(null);
init(null, R.attr.lottieAnimationViewStyle);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This matches what I think is the convention - to specify the default style attr even if programmatically creating the view.

I think it's conventional (at least in MaterialDesignComponents-Android/AppCompat) to chain constructors:

public LottieAnimationView(Context context) {
  this(context, null);
}

public LottieAnimationView(Context context, AttributeSet attrs) {
  this(context, attrs, R.attr.lottieAnimationViewStyle);
}

public LottieAnimationView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  init(attrs, defStyleAttr);
}

but I left it as-is, since I'm not sure what the consequences are if someone was relying on the fact that they don't chain.

@gpeal gpeal merged commit 708b54b into airbnb:master Mar 2, 2020
nihad92 pushed a commit to nihad92/lottie-android that referenced this pull request May 19, 2020
nihad92 pushed a commit to nihad92/lottie-android that referenced this pull request May 19, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for defStyleAttr to LottieAnimationView
2 participants