GithubHelp home page GithubHelp logo

getstream / avatarview-android Goto Github PK

View Code? Open in Web Editor NEW
431.0 4.0 24.0 18.74 MB

✨ Supports loading profile images with fractional styles, shapes, borders, indicators, and initials for Android.

Home Page: https://getstream.github.io/avatarview-android/

License: Apache License 2.0

Kotlin 100.00%
android kotlin android-library image coil glide profile loading loading-images

avatarview-android's Introduction



License API Build Status Android Weekly Dokka


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


Preview

Contribution 💙

AvatarView is maintained by Stream. If you’re interested in adding powerful In-App Messaging to your app, check out the Stream Chat Tutorial for Android! Also, anyone can contribute to improving code, docs, or something following our Contributing Guideline.

Blog Posts

Learn how to create stylish, highly-customized profile images using AvatarView for Android.

Download

Maven Central

Gradle

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

allprojects {
    repositories {
        mavenCentral()
    }
}

Next, add the below dependency to your module's build.gradle file.

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

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 your project is using the same Coil version or exclude Coil dependencies to adapt yours.

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

SNAPSHOT

See how to import the snapshot

Including the SNAPSHOT

Snapshots of the current development version of AvatarView are available, which track the latest versions.

To import snapshot versions on your project, add the code snippet below on your gradle file.

repositories {
   maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
}

Next, add the below dependency to your module's build.gradle file.

dependencies {
    implementation "io.getstream:avatarview-coil:1.0.7-SNAPSHOT"
    implementation "io.getstream:avatarview-glide:1.0.7-SNAPSHOT"
}

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 Images with Fractional Style

AvatarView supports loading up to four images with the fractional 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 fractional formats to your taste.

Loading Placeholder

We can set a placeholder to show a placeholder during 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

Error Placeholder

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 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)
}

Border

You can customize border relevant attributes as in the example below:

<io.getstream.avatarview.AvatarView
    android:layout_width="110dp"
    android:layout_height="110dp"
    app:avatarViewBorderColor="@color/white"
    app:avatarViewBorderWidth="3dp" />

Also, you can make a gradient for the border with an avatarViewIndicatorBorderColorArray attribute. First, declare an array of color in you colors.xml file as in the example below:

colors.xml

<array name="rainbow">
    <item>@color/red</item>
    <item>@color/orange</item>
    <item>@color/yellow</item>
    <item>@color/chartreuse</item>
    <item>@color/green</item>
</array>

Next, apply the color array with the avatarViewBorderColorArray attribute instread of the avatarViewBorderColor as in the below example:

<io.getstream.avatarview.AvatarView
    android:layout_width="110dp"
    android:layout_height="110dp"
    app:avatarViewBorderColorArray="@color/white"
    app:avatarViewBorderWidth="3dp" />

Shape

AvatarView supports two shapes; circle and rounded rect. You can customize the shapes as in the example below:

Circle

You can set the shape as a circle by setting the avatarViewShape attribute to circle.

<io.getstream.avatarview.AvatarView
    android:layout_width="110dp"
    android:layout_height="110dp"
    app:avatarViewShape="circle" />

Rounded Rect

You can set the shape as a rounded rect by setting the avatarViewShape attribute to rounded_rect. Also, you can customize a radius of the border with an avatarViewBorderRadius attribute.

<io.getstream.avatarview.AvatarView
    android:layout_width="110dp"
    android:layout_height="110dp"
    app:avatarViewShape="rounded_rect"
    app:avatarViewBorderRadius="21dp"
    />

Indicator

AvatarView supports drawing an indicator, which can be used for presenting a user online status or badges. You can enable it by giving true for an avatarViewIndicatorEnabled attribute as in the example below:

<io.getstream.avatarview.AvatarView
    android:layout_width="110dp"
    android:layout_height="110dp"
    app:avatarViewIndicatorEnabled="true"
    app:avatarViewIndicatorColor="@color/green"
    app:avatarViewIndicatorBorderColor="@color/white"
    app:avatarViewIndicatorSizeCriteria="9"
    app:avatarViewIndicatorBorderSizeCriteria="10"
    app:avatarViewIndicatorPosition="bottomRight" />

As you can see above, you can customize the color of the indicator and border of the indicator, size criteria, and position. Also, you can customize the whole indicator with your custom drawable resource:

<io.getstream.avatarview.AvatarView
    android:layout_width="110dp"
    android:layout_height="110dp"
    app:avatarViewIndicatorDrawable="@drawable/stream" />

Initials

AvatarView supports drawing initials. You can draw and customize initials instead of loading an image over 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 is 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

AvatarView with Glide

We highly recommend using AvatarView-Coil to load images if possible. However, you can also use Glide instead.

👉 Check out AvatarView-Glide.

Stream Integration

Maven Central

AvatarView supports integrating features with Stream Chat SDK for Android. First, You can simply integrate with Stream Chat SDK by adding the dependency below:

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 from the name will be loaded.

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

For more details, you can check out the Dokka-AvatarView.

Attributes Type Description
avatarViewBorderColor color AvatarView border color
avatarViewBorderColorArray array AvatarView border color array
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
avatarViewIndicatorBorderColorArray array Border color array 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 2022 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.

avatarview-android's People

Contributors

skydoves avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

avatarview-android's Issues

App Gets Crashed when textInitials Contains Multiple spaces in between. For eg :- "Test Name"

Hi,
Thanks for this amazing library, I found one issue here :-
When we set textInitials which contains multiple spaces in between at that time app is crashed :-
Eg :- When I try to set textInitials = Test Name

So main issue is here :-
/** Returns parsed initials from a String. */ internal val String.parseInitials: String @JvmSynthetic inline get() { val textList = trim().split(" ") return when { textList.size > 1 -> "${textList[0][0]}${textList[1][0]}" textList[0].length > 1 -> "${textList[0][0]}${textList[0][1]}" textList[0].isNotEmpty() -> "${textList[0][0]}" else -> "" }.uppercase() }

Now now when `Test     Name` is split it gives [Test, , ,Name] here second and third space is empty

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.

support for Java

Is the library support for Java? If yes, can you include a sample for java using. Thank you so much for this awesome lib.

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) }

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?

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

Initials: Ability to change Font or apply Theme Font

I tested it as an replacement for an Initials Avatar View.
It's great and has more customizability than the other library I used. However it's lacking the ability to change the font or apply the Theme's Font set in styles.xml.

It would be great if that funcionality could be added.

The photo goes out of the round line

1111

== Here My Code:
loadImage(
data = imageUrl,
requestBuilder = Glide.with(context)
.asDrawable()
.override(120, 120)
.circleCrop()
.dontAnimate()
.listener(object : RequestListener {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: com.bumptech.glide.request.target.Target?,
isFirstResource: Boolean
): Boolean {
return false
}
override fun onResourceReady(
resource: Drawable?,
model: Any?,
target: com.bumptech.glide.request.target.Target?,
dataSource: DataSource?,
isFirstResource: Boolean
): Boolean {
// Image loaded successfully
return false
}
})

== Dependency
//Image Avatar View
implementation "io.getstream:avatarview-coil:1.0.7"
implementation "io.getstream:avatarview-glide:1.0.7"
implementation("com.github.Commit451.coil-transformations:transformations:2.0.2")
implementation("io.coil-kt:coil:2.2.2")

Please check this one issue and let me know if it is fix

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.

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.