🖼 Supports loading profile images with segmented style, shapes, borders, indicators, and initials for Android.

Overview

AvatarView


AvatarView supports loading profile images with segmented style, borders, indicators, and initials for Android.


License API Build Status


Download

Maven Central

Gradle

Add the below codes to your root build.gradle file (not your module build.gradle file).

allprojects {
    repositories {
        mavenCentral()
    }
}

And add a dependency code to your module's build.gradle file.

dependencies {
    implementation "io.getstream:avatarview-coil:1.0.0"
}

Note: The io.getstream.avatarview-coil dependency includes Coil to load images internally. So if you're using Coil in your project, please make sure you project is using the same Coil version or exclude Coil dependencies to adapt yours.

We're highly recommend using AvatarView-Coil to load images. However, if you'd more prefer to use Glide, you can use AvatarView-Glide instead.

Usage

First, add the following XML namespace inside your XML layout file.

xmlns:app="http://schemas.android.com/apk/res-auto"

AvatarView in XML layout

You can customize AvatarView in your XML layout by setting attributes.

<io.getstream.avatarview.AvatarView
    android:layout_width="110dp"
    android:layout_height="110dp"
    app:avatarViewBorderColor="@color/yellow"
    app:avatarViewBorderWidth="3dp"
    app:avatarViewIndicatorBorderColor="@color/white"
    app:avatarViewIndicatorBorderSizeCriteria="10"
    app:avatarViewIndicatorColor="@color/md_green_100"
    app:avatarViewIndicatorEnabled="true"
    app:avatarViewIndicatorPosition="bottomRight"
    app:avatarViewIndicatorSizeCriteria="9"
    app:avatarViewInitialsTextStyle="bold"
    app:avatarViewShape="circle" />

Loading Single Image

You can load an image on your AvatarView by using the loadImage method as in the example below:

avatarView.loadImage(data)

The default supported data types are String, Uri, HttpUrl , File, DrawableRes, Drawable, and Bitmap.
You can also set a place holder and request listeners as in the example below:

avatarView.loadImage(
    data = data,
    placeholder = drawable,
    onStart = {
        // started requesting an image
    },
    onComplete = {
        // completed requesting an image
    }
)

Loading Segmented Style Image

AvatarView supports loading up to four images with the segmented style as in the example below:

avatarView.loadImage(
  data = listof(url1, url2, url3, url4) 
)

We can set the maximum section size of the avatar when we load multiple images by using the avatarViewMaxSectionSize attribute as in the exmample below:

app:avatarViewMaxSectionSize="4"

The default value is 4, and you can set the segmentation styles on your taste.

PlaceHolder

We can set a placeholder to show a placeholder when loading an image as in the example below:

app:avatarViewPlaceholder="@drawable/stream"

Or we can set a drawable manually on the AvatarView.

avatarView.placeholder = drawable

ErrorPlaceHolder

We can set an error placeholder to show a placeholder when the request failed as in the example below:

app:avatarViewErrorPlaceholder="@drawable/stream"

Or we can set a drawable manually on the AvatarView.

avatarView.errorPlaceholder = drawable

Custom ImageRequest

You can customize the ImageRequest and provide information to load an image as in the example below:

avatarView.loadImage(
  data = data
) {
    crossfade(true)
    crossfade(300)
    transformations(CircleCropTransformation())
    lifecycle(this@MainActivity)
}

Drawing Initials

AvatarView supports drawing up to first two initials. You can draw and customize initials instead of loading an image on the AvatarView as in the example below:

<io.getstream.avatarview.AvatarView
    android:layout_width="110dp"
    android:layout_height="110dp"
    app:avatarViewInitials="AB"
    app:avatarViewInitialsBackgroundColor="@color/skyBlue"
    app:avatarViewInitialsTextColor="@color/white"
    app:avatarViewInitialsTextSize="21sp"
    app:avatarViewInitialsTextSizeRatio="0.33"
    app:avatarViewInitialsTextStyle="bold" />

AvatarCoil

The io.getstream.avatarview-coil dependency supports customizing the internal Coil that called AvatarCoil.

Custom ImageLoader

You can load images with your custom ImageLoader to load AvatarView by setting an ImageLoaderFactory on the AvatarCoil. Then all AvatarView will be loaded by the provided ImageLoader as in example the below:

AvatarCoil.setImageLoader(
    AvatarImageLoaderFactory(context) {
        crossfade(true)
        crossfade(400)
        okHttpClient {
            OkHttpClient.Builder()
                .cache(CoilUtils.createDefaultCache(context))
                .build()
        }
    }
)

Custom AvatarBitmapFactory

Loading custom Avatar bitmaps

Avatar bitmaps are created by the internal bitmap factory called AvatarBitmapFactory. However, you can override the image loading methods and provide your own bitmap loader like the example below:

Note: The loadAvatarBitmapBlocking method takes precedence over this one if both are implemented.

AvatarCoil.setAvatarBitmapFactory(
    object : AvatarBitmapFactory(context) {
        override suspend fun loadAvatarBitmap(data: Any?): Bitmap? {
            return withContext(Dispatchers.IO) {
                val imageResult = context.imageLoader.execute(
                    ImageRequest.Builder(context)
                       .headers(AvatarCoil.imageHeadersProvider.getImageRequestHeaders().toHeaders())
                       .data(data)
                       .build()
                )
                (imageResult.drawable as? BitmapDrawable)?.bitmap
            }
        }
    }
)

If you don't use coroutines, you can override loadAvatarBitmapBlocking method instead.

AvatarCoil.setAvatarBitmapFactory(
    object : AvatarBitmapFactory(context) {
        override fun loadAvatarBitmapBlocking(): Bitmap? {
            return // return your loaded Bitmap
        }
    }
)

Loading custom Avatar placeholder bitmaps

Basically, you can draw your placeholder drawable by setting the placeholder property on the AvatarView. However, you can provide your own bitmap loader by overriding the loadAvatarPlaceholderBitmap method like the example below:

Note: The loadAvatarPlaceholderBitmap will be executed if the previous image request failed. And the loadAvatarPlaceholderBitmapBlocking method takes precedence over this one if both are implemented.

AvatarCoil.setAvatarBitmapFactory(
    object : AvatarBitmapFactory(context) {
        override fun loadAvatarPlaceholderBitmap(): Bitmap? {
            return // return your loaded placeholder Bitmap
        }
    }
)

If you don't use coroutines, you can override loadAvatarPlaceholderBitmapBlocking method instead like the example below:

AvatarCoil.setAvatarBitmapFactory(
    object : AvatarBitmapFactory(context) {
        override fun loadAvatarPlaceholderBitmapBlocking(): Bitmap? {
            return // return your loaded placeholder Bitmap
        }
    }
)

Custom ImageHeadersProvider

If you're using your own CDN, you can set the imageHeadersProvider on AvatarCoil to load image data with your own header as in the example below:

AvatarCoil.imageHeadersProvider = yourImageHeadersProvider

Stream Integration

Maven Central

We're highly recommend using the internal AvatarView in the Stream Chat SDK. However if you'd like to integrate this library with it, you can simply integrate with Stream Chat SDK by adding the below dependency:

dependencies {
    implementation "io.getstream:avatarview-stream-integration:$avatarview_version"
}

Next, you should set the StreamAvatarBitmapFactory on the AvatarCoil as in the below:

AvatarCoil.setAvatarBitmapFactory(StreamAvatarBitmapFactory(context))

Basically, it will load the image extra data of the User. But if there's no valid image data, the initials by the name will be drawn.

Then you can set your User model to the AvatarView as in the example below:

val currentUser = ChatClient.instance().getCurrentUser()
avatarView.setUserData(currentUser)

Also, you can set your Channel model to the AvatarView as in the example below:

avatarView.setChannel(channel)

The channel image will be loaded. But if there is no valid channel image, an image composed of members will be loaded.

AvatarView Attributes

Attributes Type Description
avatarViewBorderColor color AvatarView border color
avatarViewBorderRadius dimension AvatarView border radius
avatarViewBorderWidth dimension AvatarView Border width
avatarViewInitials string AvatarView initials to be drawn instead of an image
avatarViewInitialsTextSize integer AvatarView initials text size
avatarViewInitialsTextSizeRatio float AvatarView initials text size ratio following the width size
avatarViewInitialsTextColor color AvatarView initials text color
avatarViewInitialsBackgroundColor color AvatarView initials background color
avatarViewInitialsTextStyle enum AvatarView initials text style
avatarViewShape enum AvatarView shapes
avatarViewIndicatorEnabled boolean Sets the visibility of the indicator
avatarViewIndicatorPosition enum Sets the position of the indicator
avatarViewIndicatorColor color Color of the indicator
avatarViewIndicatorBorderColor color Border color of the indicator
avatarViewIndicatorSizeCriteria float Size criteria of the indicator
avatarViewIndicatorBorderSizeCriteria float Border Size criteria of the indicator
avatarViewSupportRtlEnabled boolean Supports RTL layout is enabled or not
avatarViewMaxSectionSize enum The maximum section size of the avatar when loading multiple images
avatarViewPlaceholder Drawable A placeholder that should be shown when loading an image
avatarViewErrorPlaceholder Drawable An error placeholder that should be shown when request failed

Find this library useful? ❤️

Support it by joining stargazers for this repository.
Also follow Stream on Twitter for our next creations!

License

Copyright 2021 Stream.IO, Inc. All Rights Reserved.

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.
Comments
  • TextDrawable is not being loaded

    TextDrawable is not being loaded

    I am using this library for name initials placeholder - https://github.com/amulyakhare/TextDrawable However, AvatarView doesn't load TextDrawable somehow Any help is appreciated

    opened by pmrzygweb 5
  • Data Loading Fail/Fallback to Initials

    Data Loading Fail/Fallback to Initials

    Hi @skydoves

    Is there any way, by that I can set a fallback to Initials. Like i provided HTTP Url and initial both. Expectation : Initially it should ajow initials when image is is downloaded then show image.

    Current behaviour : If i gave both url and initials then it shows Initials always.

    Correct me I missed something.

    good first issue 
    opened by yogeshpaliyal 3
  • Getting initial image drawable

    Getting initial image drawable

    I was trying to get the drawable of the initial image in order to download it to local storage, however, it is not possible now. I was using this piece of code avatarView.drawable.toBitmap() it throws null pointer exception, stating that drawable is null all the time.

    opened by Clar1fy 2
  • Loading Images with Fractional Style with Glide.

    Loading Images with Fractional Style with Glide.

    Hi, there seems to be a bug when uploading multiple images with Glide. For example, calling the avatarView1.loadImage(cats.take(4)) method will result in an error:

    java.lang.IllegalStateException: You can't start or clear loads in RequestListener or Target callbacks. If you're trying to start a fallback request when a load fails, use RequestBuilder#error(RequestBuilder). Otherwise consider posting your into() or clear() calls to the main thread using a Handler instead.
            at com.bumptech.glide.request.SingleRequest.assertNotCallingCallbacks(SingleRequest.java:289)
            at com.bumptech.glide.request.SingleRequest.clear(SingleRequest.java:309)
            at com.bumptech.glide.manager.RequestTracker.clearAndRemove(RequestTracker.java:72)
            at com.bumptech.glide.RequestManager.untrack(RequestManager.java:660)
            at com.bumptech.glide.RequestManager.untrackOrDelegate(RequestManager.java:628)
            at com.bumptech.glide.RequestManager.clear(RequestManager.java:624)
            at io.getstream.avatarview.glide.AvatarBitmapLoader$loadBitmaps$1$2.invoke(AvatarBitmapLoader.kt:91)
            at io.getstream.avatarview.glide.AvatarBitmapLoader$loadBitmaps$1$2.invoke(AvatarBitmapLoader.kt:90)
    

    The error refers to this code

    awaitClose {
                requestManager.clear(avatarViewTarget)
            }
    

    Since Glide loads images on the main thread, it seems that we can fix this problem by adding launch(Dispatchers.Main) to

       launch() {
            val avatarResults: ArrayList<AvatarResult> = arrayListOf()
            val avatarResultFlow = AvatarBitmapLoader.loadBitmaps(
                requestManager = Glide.with(this@collectAndCombineBitmaps),
                data = data,
                errorPlaceholder = errorPlaceholder
            )
    

    But not sure if that would be the right decision.

    bug 
    opened by Normalnick12 2
  • Using avatarview in recycler adapter doesn't work

    Using avatarview in recycler adapter doesn't work

    Using avatarview in recycler adapter doesn't work

    When I try to inflate layout this error comes 2022-07-23 14:49:59.117 15628-15628/com.codewithritom.anonchat E/AndroidRuntime: FATAL EXCEPTION: main Process: com.codewithritom.anonchat, PID: 15628 android.view.InflateException: Binary XML file line #8 in com.codewithritom.anonchat:layout/searched_user_item: Binary XML file line #8 in com.codewithritom.anonchat:layout/searched_user_item: Error inflating class io.getstream.avatarview.AvatarView Caused by: android.view.InflateException: Binary XML file line #8 in com.codewithritom.anonchat:layout/searched_user_item: Error inflating class io.getstream.avatarview.AvatarView Caused by: java.lang.reflect.InvocationTargetException at java.lang.reflect.Constructor.newInstance0(Native Method) at java.lang.reflect.Constructor.newInstance(Constructor.java:343) at android.view.LayoutInflater.createView(LayoutInflater.java:863) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1019) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:970) at android.view.LayoutInflater.rInflate(LayoutInflater.java:1149) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1110) at android.view.LayoutInflater.inflate(LayoutInflater.java:692) at android.view.LayoutInflater.inflate(LayoutInflater.java:542) at com.codewithritom.anonchat.models.SearchedUsersAdapter.onCreateViewHolder(SearchedUsersAdapter.kt:25) at com.codewithritom.anonchat.models.SearchedUsersAdapter.onCreateViewHolder(SearchedUsersAdapter.kt:19) at androidx.recyclerview.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:7295) at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6416) at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6300) at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6296) at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2330) at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1631) at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1591) at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:668) at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4309) at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:4012) at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4578) at android.view.View.layout(View.java:23488) at android.view.ViewGroup.layout(ViewGroup.java:6575) at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1103) at android.view.View.layout(View.java:23488) at android.view.ViewGroup.layout(ViewGroup.java:6575) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332) at android.widget.FrameLayout.onLayout(FrameLayout.java:270) at android.view.View.layout(View.java:23488) at android.view.ViewGroup.layout(ViewGroup.java:6575) at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1103) at android.view.View.layout(View.java:23488) at android.view.ViewGroup.layout(ViewGroup.java:6575) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332) at android.widget.FrameLayout.onLayout(FrameLayout.java:270) at android.view.View.layout(View.java:23488) at android.view.ViewGroup.layout(ViewGroup.java:6575) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1841) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673) at android.widget.LinearLayout.onLayout(LinearLayout.java:1582) at android.view.View.layout(View.java:23488) at android.view.ViewGroup.layout(ViewGroup.java:6575) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332) at android.widget.FrameLayout.onLayout(FrameLayout.java:270) at android.view.View.layout(View.java:23488) at android.view.ViewGroup.layout(ViewGroup.java:6575) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1841) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673) 2022-07-23 14:49:59.118 15628-15628/com.codewithritom.anonchat E/AndroidRuntime: at android.widget.LinearLayout.onLayout(LinearLayout.java:1582) at android.view.View.layout(View.java:23488) at android.view.ViewGroup.layout(ViewGroup.java:6575) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332) at android.widget.FrameLayout.onLayout(FrameLayout.java:270) at com.android.internal.policy.DecorView.onLayout(DecorView.java:867) at android.view.View.layout(View.java:23488) at android.view.ViewGroup.layout(ViewGroup.java:6575) at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:4119) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3495) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2416) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9478) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1242) at android.view.Choreographer.doCallbacks(Choreographer.java:996) at android.view.ChoreographerExtImpl.checkScrollOptSceneEnable(ChoreographerExtImpl.java:383) at android.view.Choreographer.doFrame(Choreographer.java:865) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1227) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:233) at android.os.Looper.loop(Looper.java:344) at android.app.ActivityThread.main(ActivityThread.java:8248) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:589) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1071) Caused by: android.content.res.Resources$NotFoundException: Can't find ColorStateList from drawable resource ID #0x7f0700b2 at android.content.res.ResourcesImpl.loadColorStateList(ResourcesImpl.java:1161) at android.content.res.Resources.loadColorStateList(Resources.java:1158) at android.content.res.TypedArray.getColor(TypedArray.java:521) at io.getstream.avatarview.AvatarView.initAttributes(AvatarView.kt:170) at io.getstream.avatarview.AvatarView.(AvatarView.kt:160) at io.getstream.avatarview.AvatarView.(AvatarView.kt:55) at io.getstream.avatarview.AvatarView.(Unknown Source:11) ... 74 more 2022-07-23 14:49:59.298 16459-16459/? E/hritom.anoncha: Unknown bits set in runtime_flags: 0x40000000 2022-07-23 14:49:59.740 16459-16494/com.codewithritom.anonchat E/QT: [QT]file does not exist 2022-07-23 14:49:59.878 16459-16459/com.codewithritom.anonchat E/OplusCustomizeRestrictionManager: sInstance is null, start a new sInstance 2022-07-23 14:50:00.049 16459-16459/com.codewithritom.anonchat E/hritom.anoncha: ofbOpen failed with error=No such file or directory 2022-07-23 14:50:00.049 16459-16459/com.codewithritom.anonchat E/hritom.anoncha: sysOpen failed with error=No such file or directory 2022-07-23 14:50:00.301 16459-16492/com.codewithritom.anonchat E/OpenGLRenderer: Device claims wide gamut support, cannot find matching config, error = EGL_SUCCESS 2022-07-23 14:50:00.314 16459-16520/com.codewithritom.anonchat E/ion: ioctl c0044901 failed with code -1: Invalid argument 2022-07-23 14:50:00.360 16459-16492/com.codewithritom.anonchat E/OpenGLRenderer: fbcNotifyFrameComplete error: undefined symbol: fbcNotifyFrameComplete 2022-07-23 14:50:00.360 16459-16492/com.codewithritom.anonchat E/OpenGLRenderer: fbcNotifyNoRender error: undefined symbol: fbcNotifyNoRender 2022-07-23 14:50:00.387 16459-16459/com.codewithritom.anonchat E/Parcel: Reading a NULL string not supported here.

    XML

    <io.getstream.avatarview.AvatarView android:id = "@+id/profile_image" android:layout_width="110dp" android:layout_height="110dp" app:avatarViewBorderColor="@drawable/color_4" app:avatarViewBorderWidth="3dp" app:avatarViewIndicatorBorderColor="@color/white" app:avatarViewIndicatorBorderSizeCriteria="10" app:avatarViewIndicatorColor="@color/black" app:avatarViewIndicatorEnabled="true" app:avatarViewIndicatorPosition="bottomRight" app:avatarViewIndicatorSizeCriteria="9" app:avatarViewInitialsTextStyle="bold" app:avatarViewShape="circle" />

    line 25 - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view: View = LayoutInflater.from(mcontext).inflate(R.layout.searched_user_item, parent, false) return ViewHolder(view) }

    opened by RitomG69 1
  • Supporting multiple avatars

    Supporting multiple avatars

    Hello and congratulations on the amazing library.

    I have a question here regarding multiple avatars. I saw you support up to 4 avatars in one view. But my case is a little bit different :

    image

    I know it's possible to implement that using a RecyclerView and some logic with the max number of avatars to be shown so you can show the +7.

    Do you intent to support a view like this in the library or is it out scope?

    enhancement 
    opened by geftimov 1
  • Using loadImage inside a ListAdapter onBindViewHolder

    Using loadImage inside a ListAdapter onBindViewHolder

    I'm trying to use AvatarView-Coil to load images inside of a ListAdapter with a ViewHolder and I'm seeing weird behavior.

    Essentially in onBindViewHolder I use loadImage to load a profile picture with a String url in an AvatarView. The initial load runs fine and displays the images. Once I reload data in the adapter onBindViewHolder gets called again, but then the images are not loaded or displayed anymore.

            holder.intialsView.loadImage(favourite.contact.profilePhoto,
                onSuccess = { _, _ ->
                    logi("###### onsuccess ${favourite.contact.profilePhoto}")
                    holder.intialsView.avatarInitials = null
                },
                onStart = {
                    logi("## loading contact profile picture for ${favourite.displayName}: ${favourite.contact.profilePhoto}")
                }, onComplete = {
                    logi("## oncomplete ${favourite.contact.profilePhoto}")
                }, onError = { _, _ ->
                    logi("## error getting profile picture ${favourite.contact.profilePhoto}")
                    holder.intialsView.avatarInitials = favourite.displayName.extractInitials()
                })
    

    The first time it runs it outputs this:

    2022-02-24 22:22:41.920 8701-8701/com.myapp I/FavouritesAdapter: ############## onBindViewHolder for User1 
    2022-02-24 22:22:41.925 8701-8701/com.myapp I/FavouritesAdapter: ## loading contact profile picture for User1: https://placekitten.com/200/200
    2022-02-24 22:22:41.925 8701-8701/com.myapp I/FavouritesAdapter: ## oncomplete https://placekitten.com/200/200
    2022-02-24 22:22:41.927 8701-8701/com.myapp I/FavouritesAdapter: ## loading contact profile picture for User1: https://placekitten.com/200/200
    2022-02-24 22:22:41.937 8701-8701/com.myapp I/FavouritesAdapter: ############## onBindViewHolder for User2
    2022-02-24 22:22:41.938 8701-8701/com.myapp I/FavouritesAdapter: ## loading contact profile picture for User2: https://placekitten.com/200/200
    2022-02-24 22:22:41.939 8701-8701/com.com.myapp I/FavouritesAdapter: ## oncomplete https://placekitten.com/200/200
    2022-02-24 22:22:41.940 8701-8701/com.myapp I/FavouritesAdapter: ## loading contact profile picture for User2: https://placekitten.com/200/200
    2022-02-24 22:22:41.992 8701-8813/com.myapp I/Builder: ## Loading image from : https://placekitten.com/200/200
    2022-02-24 22:22:41.993 8701-8868/com.myapp I/Builder: ## Loading image from : https://placekitten.com/200/200
    2022-02-24 22:22:42.180 8701-8701/com.myapp I/FavouritesAdapter: ###### onsuccess https://placekitten.com/200/200
    2022-02-24 22:22:42.181 8701-8701/com.myapp I/FavouritesAdapter: ###### onsuccess https://placekitten.com/200/200
    2022-02-24 22:22:42.298 8701-8701/com.myapp I/FavouritesAdapter: ## oncomplete https://placekitten.com/200/200
    2022-02-24 22:22:42.298 8701-8701/com.myapp I/FavouritesAdapter: ## oncomplete https://placekitten.com/200/200
    

    The Loading image from... statements are from the ImageLoader requestInterceptor

    Then, a bit later when reloading the data it outputs this:

    2022-02-24 22:22:47.306 8701-8701/com.myapp I/FavouritesAdapter: ############## onBindViewHolder for User1
    2022-02-24 22:22:47.308 8701-8701/com.myapp I/FavouritesAdapter: ## loading contact profile picture for User1 https://placekitten.com/200/200
    2022-02-24 22:22:47.309 8701-8701/com.myapp I/FavouritesAdapter: ## oncomplete https://placekitten.com/200/200
    2022-02-24 22:22:47.311 8701-8701/com.myapp I/FavouritesAdapter: ## loading contact profile picture for User1: https://placekitten.com/200/200
    2022-02-24 22:22:47.312 8701-8701/com.myapp I/FavouritesAdapter: ## oncomplete https://placekitten.com/200/200
    2022-02-24 22:22:47.325 8701-8701/com.myapp I/FavouritesAdapter: ############## onBindViewHolder for User2
    2022-02-24 22:22:47.327 8701-8701/com.myapp I/FavouritesAdapter: ## loading contact profile picture for User2: https://placekitten.com/200/200
    2022-02-24 22:22:47.328 8701-8701/com.myapp I/FavouritesAdapter: ## oncomplete https://placekitten.com/200/200
    2022-02-24 22:22:47.330 8701-8701/com.myapp I/FavouritesAdapter: ## loading contact profile picture for User2: https://placekitten.com/200/200
    2022-02-24 22:22:47.330 8701-8701/com.myapp I/FavouritesAdapter: ## oncomplete https://placekitten.com/200/200
    

    The weird behavior I'm seeing is this:

    • the onStart seems to be fired twice when I call loadImage
    • the onComplete fires twice as well, once immediately after the first onStart, and a second time after onSuccess.
    • on the second run after rebinding the data, onStart is fired twice again
    • onComplete fires twice again, both immediately after the onStart
    • no Loading image from on the second run, presumably because of caching in the ImageLoader
    • on this second run onSuccess is never called (also because of caching?)
    • on this second run no images are displayed.

    Am I misunderstanding the api or could this be a bug? I expected each call to loadImage to result in only one call to onStart and one call to onComplete/onSuccess and the images to be displayed after onComplete.

    I'm using io.getstream:avatarview-coil:1.0.3

    opened by vbsteven 4
Releases(1.0.7)
  • 1.0.7(Oct 5, 2022)

    What's Changed

    • Update Kotlin to 1.6.21 by @skydoves in https://github.com/GetStream/avatarview-android/pull/33
    • Bump Stream SDK to 5.4.0 by @skydoves in https://github.com/GetStream/avatarview-android/pull/34
    • Bump Stream SDK to 5.5.0 by @skydoves in https://github.com/GetStream/avatarview-android/pull/35
    • Update Stream SDK to 5.7.0 and bump dependencies by @skydoves in https://github.com/GetStream/avatarview-android/pull/38
    • Update AGP to 7.3.0 and Kotlin to 1.7.20 by @skydoves in https://github.com/GetStream/avatarview-android/pull/40
    • Bump Stream SDK to 5.11.1 by @skydoves in https://github.com/GetStream/avatarview-android/pull/41
    • Update Coil to 2.2.1 and Glide to 4.14.1 by @skydoves in https://github.com/GetStream/avatarview-android/pull/42

    Full Changelog: https://github.com/GetStream/avatarview-android/compare/1.0.6...1.0.7

    Source code(tar.gz)
    Source code(zip)
  • 1.0.6(Jun 17, 2022)

    What's Changed

    • Update compile & target sdk to 32 by @skydoves in https://github.com/GetStream/avatarview-android/pull/27
    • Update AGP to 7.1.3 and Coil to 2.1.0 by @skydoves in https://github.com/GetStream/avatarview-android/pull/28
    • Update binary validator to 0.10.1 by @skydoves in https://github.com/GetStream/avatarview-android/pull/32
    • Add a license format for XML by @skydoves in https://github.com/GetStream/avatarview-android/pull/29

    Full Changelog: https://github.com/GetStream/avatarview-android/compare/1.0.5...1.0.6

    Source code(tar.gz)
    Source code(zip)
  • 1.0.5(May 11, 2022)

    🎉 A new version 1.0.5 was released! 🎉

    What's Changed

    • Update Gradle to 7.4.2 and dependencies by @skydoves in https://github.com/GetStream/avatarview-android/pull/21
    • Bump Glide to version 4.13.2 by @skydoves in https://github.com/GetStream/avatarview-android/pull/25
    • Bump Coil to version 2.0.0 by @skydoves in https://github.com/GetStream/avatarview-android/pull/26

    Full Changelog: https://github.com/GetStream/avatarview-android/compare/1.0.4...1.0.5

    Source code(tar.gz)
    Source code(zip)
  • 1.0.4(Apr 1, 2022)

    What's Changed

    • Bump Glide to 4.13.0 and AGP to 7.1.2 by @skydoves in https://github.com/GetStream/avatarview-android/pull/15
    • Migrate Stream SDK to 5.0.2 by @skydoves in https://github.com/GetStream/avatarview-android/pull/20

    Full Changelog: https://github.com/GetStream/avatarview-android/compare/1.0.3...1.0.4

    Source code(tar.gz)
    Source code(zip)
  • 1.0.3(Feb 3, 2022)

    ✨ Released a new version 1.0.3! ✨

    What's Changed

    • Fixed Loading Images with Fractional Style with Glide. #13
    • Run collect and combine methods for bitmaps on the Main dispatcher by @skydoves in https://github.com/GetStream/avatarview-android/pull/14
    • Bump Stream Chat SDK to 4.27.0 by @skydoves in https://github.com/GetStream/avatarview-android/pull/12

    Full Changelog: https://github.com/GetStream/avatarview-android/compare/1.0.2...1.0.3

    Source code(tar.gz)
    Source code(zip)
  • 1.0.2(Jan 13, 2022)

    ✨ Released a new version 1.0.2! ✨

    preview/dokka-avatarview.svg

    What's Changed

    • Deploy Dokka for AvatarView on GitHub by @skydoves
    • Set up Dokka multi-module task by @skydoves in https://github.com/GetStream/avatarview-android/pull/8
    • Add an .editconfig file to configure IDE set up by @skydoves in https://github.com/GetStream/avatarview-android/pull/9
    • Bump Stream SDK to 4.26.0 by @skydoves in https://github.com/GetStream/avatarview-android/pull/10
    • Update spotless License configurations by @skydoves in https://github.com/GetStream/avatarview-android/pull/11

    Full Changelog: https://github.com/GetStream/avatarview-android/compare/1.0.1...1.0.2

    Source code(tar.gz)
    Source code(zip)
  • 1.0.1(Jan 6, 2022)

    ✨ Released a new version 1.0.1! ✨

    What's Changed

    • Feature: Added onSuccess and onFailed listeners for AvatarView-Coil by @skydoves in https://github.com/GetStream/avatarview-android/pull/3
    • Feature: Added BorderColorArray and IndicatorBorderColorArray by @skydoves in https://github.com/GetStream/avatarview-android/pull/5
    • Improve attribute customization documents by @skydoves in https://github.com/GetStream/avatarview-android/pull/7
    • Update Snapshots documentation by @skydoves in https://github.com/GetStream/avatarview-android/pull/4
    • Bump Stream SDK to 4.25.0 for Stream-Integration by @skydoves in https://github.com/GetStream/avatarview-android/pull/1

    New Contributors

    • @skydoves made their first contribution in https://github.com/GetStream/avatarview-android/pull/1

    Full Changelog: https://github.com/GetStream/avatarview-android/compare/1.0.0...1.0.1

    Source code(tar.gz)
    Source code(zip)
  • 1.0.0(Dec 17, 2021)

    🎉 Released the first version 1.0.0! 🎉

    Avatarview

    Includes the main custom view AvatarView which draws shapes, borders, indicators, and initials with fully customizable options. And includes the multi-type(segmented style) image provider which is called AvatarBitmapCombiner.

    Avatarview-Coil

    Helps to load the bitmap images over the AvatarView with Coil. Provides custom image loader/requester, bitmap factory, and custom default/error placeholder provider.

    Avatarview-Glide

    Helps to load bitmap images over the AvatarView with Glide. Provides custom image loader and loading segmented style image.

    Avatarview-Stream-Integration

    Helps to load avatar images with Stream SDK’s client models such as User and Channel. Supports loading segmented style image by using the Channel, and drawing the default avatar image with initials.

    Source code(tar.gz)
    Source code(zip)
Owner
Stream
Build scalable newsfeeds, activity streams, chat and messaging in a few hours instead of weeks
Stream
🚀 React Native Segmented Control, Pure Javascript for iOS and Android

Installation Add the dependency: npm i react-native-segmented-control-2 Peer Dependencies Zero Dependency ?? Usage Import import SegmentedControl from

FreakyCoder 11 Nov 10, 2022
The app has got fullscreen Turkey map via Huawei Map. App selects random province and shows it borders on the map than user will try to guess the provinces name.

Il Bil App Introduction I will introduce you to how to implement Account Kit, Map Kit, Game Service. About the game: The app has got fullscreen Turkey

Gökhan YILMAZ 4 Aug 2, 2022
Icons, Borders, Radius ... for Android buttons

⚠️ This library was made years ago when it wasn't that easy to customize Android buttons like today. I highly recommend you to use Material Design but

Mehdi Sakout 1.8k Dec 10, 2022
🛡️ Android security (camera/microphone dots indicators) app using Hilt, Animations, Coroutines, Material, StateFlow, Jetpack based on MVVM architecture.

??️ Android security app using Hilt, Animations, Coroutines, Material, StateFlow, Jetpack (Room, ViewModel, Paging, Security, Biometrics, Start-up) based on MVVM architecture.

null 639 Jan 6, 2023
A Android Web IDE supports code auto-completion and highlight, plugin (Supports Html, Css, JS, Json, Php etc)

WebDevOps A Android Web IDE supports code auto-completion and highlight, plugin (Supports Html, Css, JS, Json, Php etc) Join us QQ group number: 10314

SuMuCheng 22 Jan 3, 2023
GitHub application fetches events, repositories and profile using GitHub APIs

GitHub application using GitHub REST API Dagger MVVM architecture Mockk Jetpack Compose Kotlin Coroutines Application pages Attention If you want to u

Marjan DavoodiNejad 6 Oct 17, 2022
Android App Development using Android Studio Project for The Swastika. It is edit profile view.

Edit_Profile_View Android App Development using Android Studio Project for The Swastika. It is edit profile view. To start with this project first is

Shradha Suryawanshi 1 Jun 12, 2022
Modern Social Profile Layout For Android

Social Profile Layout Modern Simple Social Profile Layout for your Android App Project Installation Just run this project on your Android Studio Proje

Yogi Prasetyawan 4 Dec 21, 2022
An efficient GitHub profile app, written in Kotlin!

GitPositive An efficient GitHub profile app, written in Kotlin! GitPositive aims to be a simple and efficient GitHub profile app, following the princi

ACM VIT 14 Oct 12, 2022
The application shows the profile of a random user

The application shows the profile of a random user

Aleksandra 1 Apr 19, 2022
A multi-platform Collins Dictionary client, supports for Desktop(Windows/Linux/MacOS) and Android.

Collins Dictionary This is a multi-platform Collins Dictionary client, supports for Desktop(Windows/Linux/MacOS) and Android. For Linux and MacOS, ple

KonYaco 57 Dec 30, 2022
Matomo wrapper for React-Native. Supports Android and iOS. Fixed issues for native platforms build that are present in the official package.

@mccsoft/react-native-matomo Matomo wrapper for React-Native. Supports Android and iOS. Fixed issues for native platforms build that are present in th

MCC Soft 4 Dec 29, 2022
The easy way to use biometric authentication in your Flutter app. Supports Fingerprint, FaceID and Iris.

BiometricX The easy way to use biometric authentication in your Flutter app. Supports Fingerprint, FaceID and Iris. Demo APK. Starting $ flutter pub a

Salman S 13 Dec 15, 2022
Linux GUI for Kuri's userspace tablet drivers. Supports non-wacom (XP-Pen, Huion, Gaomon) graphics tablets and pen displays

Kuri's Userspace tablet driver utility (GUI) This is a new GUI implementation for the userland driver I've written here: https://github.com/kurikaesu/

Aren Villanueva 12 Jan 4, 2023
Wiremock-testing - WireMock - A great library to mock APIs in your tests and supports Junit5

WireMock Testing WireMock is a great library to mock APIs in your tests and supp

Roger Viñas 1 Oct 4, 2022
IMCL is a Minecraft launcher which supports Mod managment, game customizing and so on.

IDEA Minecraft Launcher A simple Minecraft launcher 简体中文 日本語 Esperanto Introduction IMCL is a Minecraft launcher which supports Mod managment, game cu

ResetPower 1 Jan 25, 2022
A Kotlin binding to webview, a tiny cross-platform webview library, supports Java and Native.

webviewko provides a Kotlin/JVM and a Kotlin/Native(experimental) binding to webview, a tiny cross-platform webview library to build modern cross-platform GUIs using WebView2, WebKit and WebKitGTK.

Winterreisender 17 Dec 30, 2022
An android library through which users can add a customized loading dialog box with Lottie Animations.

CustomLottieDialogBox About CustomLottieDialogBox is an android library which facilitate developers to add customized loading Dialog-Boxes to their an

Siddharth Singh 7 Aug 10, 2022
Social media app but with new features like translate messages and posts , support video & images as posts , chat and notifications , etc...

social-media-app Social media app but with new features like translate messages and posts , support video & images as posts , chat and notifications ,

Kareem Aboelatta 15 Dec 13, 2022