15

How would I go about making a custom indicator that would use a drawable object with a custom animation for the SwipeRefreshLayout?

I looked over the source code for SwipeRefreshLayout and I noticed the CircleImageView object was private.

Is there anyway to modify the ImageView?

AndyRoid
  • 5,062
  • 8
  • 38
  • 73

4 Answers4

29

You can change the drawable via reflection, not sure how good this idea is. Something like :

mSwipeRefreshLayout = (SwipeRefreshLayout)findViewById(R.id.your_swiperefresh_id);
try {
    Field f = mSwipeRefreshLayout.getClass().getDeclaredField("mCircleView");
    f.setAccessible(true);
    ImageView img = (ImageView)f.get(mSwipeRefreshLayout);
    img.setImageResource(R.drawable.your_drawable_file);
} catch (NoSuchFieldException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
}
abhishesh
  • 3,246
  • 18
  • 20
  • Wonder how this effects the MaterialProgressDrawable object – AndyRoid Oct 28 '15 at 19:27
  • this would only change the drawable – abhishesh Oct 28 '15 at 19:28
  • I would like to put a custom drawable, but I'm concerned about the CircleImageView. See link: https://github.com/android/platform_frameworks_support/blob/master/v4/java/android/support/v4/widget/CircleImageView.java testing it out now – AndyRoid Oct 28 '15 at 19:29
  • I checked using simple drawable, but not with custom drawable – abhishesh Oct 28 '15 at 19:32
  • Is there any way to add animations to this drawable? Like change its color? If there is a workaround for that it would satisfy this answer. – AndyRoid Oct 28 '15 at 19:34
  • Write your own MaterialProgressDrawable (like MaterialProgressDrawable extends Drawable implements Animatable) and set it using img.setImageDrawable(materialProgressDrawable). Its gonna work – abhishesh Oct 28 '15 at 19:47
  • okay! Im going to test this out really quick if it works, you're awesome! – AndyRoid Oct 28 '15 at 20:04
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/93620/discussion-between-abhishesh-and-andyroid). – abhishesh Oct 28 '15 at 20:04
  • Will Android's SecurityManager prevent me from using this in Production? – AndyRoid Oct 28 '15 at 20:40
  • @BMM which loader you want to hide?? If you dont want to use swipe to refresh, you can silently update without notifying user – abhishesh Jan 17 '17 at 10:37
  • I used this snippet but my loader is not visible now. only the background circle is shown. Any idea how to show that? – Ashwani May 24 '17 at 07:09
3

Try https://github.com/liaohuqiu/android-Ultra-Pull-To-Refresh. Modify System widget is troublesome.

tiny sunlight
  • 6,231
  • 3
  • 21
  • 42
1

If you don't want to use reflection like in example above you could get child from your SwipeRefreshLayout with 0 index. It will CircleImageView so you could set any Drawable to it.

0

This might be very late to answer but here is the solution to customize and also play the animation:-

final private LottieDrawable ld = new LottieDrawable();
Field f = swipeRefreshLayout.getClass().getDeclaredField("mCircleView");
            f.setAccessible(true);
            ImageView imgVW = (ImageView)f.get(swipeRefreshLayout);
            ld.setBounds(0, 0, 64, 64);
            @SuppressLint("WrongThread") LottieResult<LottieComposition> result = LottieCompositionFactory.fromAssetSync(App.activity, "LottieSpinner.json");
            ld.setComposition(result.getValue());
            ld.setRepeatCount(LottieDrawable.INFINITE);
            imgVW.setImageDrawable(ld);

Inside your SwipeRefreshLayout listener:-

swipeRefreshLayout.setOnRefreshListener(() -> {
ld.playAnimation();
})

Once network call is finished:-

void stop() {
    ld.stop()
}
Hussain Shabbir
  • 14,801
  • 5
  • 40
  • 56