Home

Awesome

AvatarView

A circular Image View with a lot of perks. Including progress animation and highlight state with borders and gradient color.

Gradle Codacy Badge Kotlin Kotlin GitHub license Say Thanks!

<div align="center"> <sub>Built with ❤︎ by Vitor Hugo Schwaab and <a href="https://github.com/vitorhugods/AvatarView/graphs/contributors"> contributors </a> </div> <br/>

Samples

<img src="/pics/ex1.png" alt="Example 1" width="300" style="max-width:100%;"><img src="/pics/ex2.png" alt="Example 1" width="300" style="max-width:100%;">
<img src="/pics/sample1.gif" alt="Example 1" width="300" style="max-width:100%;"><img src="/pics/sample2.gif" alt="Example 1" width="300" style="max-width:100%;">

Supports initials if no image is provided:

<img src="/pics/initials.png" alt="Initials" width="200" style="max-width:100%;">

Thanks to @anoop44

Supports a badge, for "online/offline" status or other use cases:

<img src="/pics/badge.png" alt="Badge" width="200" style="max-width:100%;">

Thanks to @p1yu5h

Demo

Watch the video or clone the repo and build the demo app

Gradle setup

Make sure you have the MavenCentral in your list of repositories.

dependencies {
    implementation("xyz.schwaab:avvylib:1.2.0")
}
dependencies {
    implementation "xyz.schwaab:avvylib:1.2.0"
}

Usage

Just add this to your XML:

    <xyz.schwaab.avvylib.AvatarView
        android:layout_width="128dp"
        android:layout_height="128dp"
        app:avvy_border_color="@color/grey400"
        app:avvy_border_highlight_color="#ff5900"
        app:avvy_border_highlight_color_end="#bf15bc"
        app:avvy_border_thickness="2dp"
        app:avvy_border_thickness_highlight="3dp"
        app:avvy_distance_to_border="5dp"
        app:avvy_highlighted="true"
        app:avvy_loading_arches="5"
        app:avvy_loading_arches_degree_area="90"/>

Add the name initials as fallback:

        app:avvy_text="Avatar View"                 //will show up as AV
        app:avvy_text_size="42sp"
        app:avvy_text_color="#ccc"

Add the badge if you want:

        app:avvy_show_badge="true"                  //Default = false
        app:avvy_badge_radius="18dp"
        app:avvy_badge_stroke_width="2dp"
        app:avvy_badge_stroke_color="@color/white"
        app:avvy_badge_position="BOTTOM_RIGHT"      //Default value

You can personalize it in Kotlin:

        avatarView.apply {
            isAnimating = false
            borderThickness = 18
            highlightBorderColor = Color.GREEN
            highlightBorderColorEnd = Color.CYAN
            numberOfArches = 0
            totalArchesDegreeArea = 80
            text = "Avatar View"
            showBadge = true
            badgePosition = BadgePosition.TOP_LEFT
        }

Or, in Java:

        avatarView.setAnimating(false);
        avatarView.setBorderThickness(18);
        avatarView.setHighlightBorderColor(Color.GREEN);
        avatarView.setHighlightBorderColorEnd(Color.CYAN);
        avatarView.setNumberOfArches(0);
        avatarView.setTotalArchesDegreeArea(80);

Custom Animations

<img src="/pics/custom_animations.gif" alt="Example 1" width="300" style="max-width:100%;">

Create an AvatarViewAnimationOrchestrator, passing at least one AvatarViewAnimator.

The setupAnimators are the first running, and they run in reverse when animation is stopping. They should not repead infinitely, so the progressAnimators can start. The progressAnimators can run indefinitely.

You don't need to use both setup and progress, just one is enough. But, by having the setup having a finite duration, and reversible, it allows for a smoother animation stop.

Example:


    val archesExpansion = object: AvatarViewAnimator{
        override val baseAnimator = ValueAnimator.ofFloat(0f, 1f).apply {
            duration = 500L
            interpolator = DecelerateInterpolator()
        }
    
        override fun onValueUpdate(animatorInterface: AvatarView.AnimatorInterface) {
            val animatedValue = baseAnimator.animatedValue as Float
            animatorInterface.updateAnimationState { currentState ->
                currentState.copy(archesExpansionProgress = animatedValue)
            }
        }
    }
    val bouncingRotation = object : AvatarViewAnimator {
        override val baseAnimator = ValueAnimator.ofFloat(0f, 1f).apply {
            repeatCount = ValueAnimator.INFINITE
            duration = 3000L
            interpolator = BounceInterpolator()
        }
    
        override fun onValueUpdate(animatorInterface: AvatarView.AnimatorInterface) {
            val animatedValue = baseAnimator.animatedValue as Float
            animatorInterface.updateAnimationState { currentState ->
                currentState.copy(rotationProgress = animatedValue)
            }
        }
    }

    avatarView.animationOrchestrator = AvatarViewAnimationOrchestrator(archesExpansion, bouncingRotation) 

Check the sample app for the full source code.

Special Thanks

The roundness of the drawables based on Henning Dodenhof's Circle ImageView

Libraries used in the demo app:

License

Copyright 2020 Vitor Hugo D. Schwaab

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.