material-calendarview icon indicating copy to clipboard operation
material-calendarview copied to clipboard

Selection circle flickers

Open mogren1158 opened this issue 7 years ago • 6 comments

When setting the height and width of the tile to be different, and then calling invalidateDecorators, the selected date's background circle will 'flicker'. It will at first appear to be sized as an oval shape, before correctly resizing itself to be a circle.

This is most easily replicable in the Custom tile width/height example.

  1. Open CustomTileDimensions.java
  2. set an onDateChangedListener to the widget.
  3. In the onDateSelected method of the listener call widget.invalidateDecorators()
  4. Launch the app and navigate to the example
  5. Change the tile height from the default, but leave the width alone
  6. Note that upon selecting a new date, the selection circle will now 'flicker'

mogren1158 avatar Apr 13 '17 15:04 mogren1158

may be are you creating a new circle every time?

pavelaizen avatar May 15 '17 20:05 pavelaizen

@pavelaizen Invalidating decorators does indeed trigger a new Drawable to be created. More specifically when the decorators are invalidated, eventually the DayView are as well, which triggers DayView.regenerateBackground(), which in turn generates a new Drawable that is then set to the background.

The issue is that when that drawable is set to the background, it's bounds are not also immediately set, causing it to appear stretched for several frames, even though the DayView.onDraw(Canvas canvas) does explicitly set the bounds. While doing some investigation into the issue, I noted that even inserting calls to setBounds inside of regenerateBackground has no effect, i.e. the drawable still appears stretched for several frames before the new bounds take effect.

While the root issue of why the bounds do not immediately take effect requires more research, a temporary fix could be to set the alpha of the drawable to 0 in regenerateBackground and then in onDraw set it to 255. There will be a slight delay of several frames before the background updates, which may be preferable to the current flickering behavior.

mogren1158 avatar May 15 '17 22:05 mogren1158

Yes! I also meet this issue? how do you fix it?need help !!

levianye avatar Sep 15 '17 04:09 levianye

The issue seems to be that View#drawBackground automatically sets the bounds of the background drawable to fill the view. However, this only happens when the internal flag mBackgroundSizeChanged is true. So on the first drawing pass, View#drawBackground sets the bounds of mCircleView to fill the view, overwriting the value set in DayView#onDraw. On the next drawing pass, mBackgroundSizeChanged is now false, so the bounds value set in DayView#onDraw sticks.

One potential fix is to have DayView#generateCircleDrawable return an InsetDrawable with the appropriate insets generated from circleDrawableRect. Then you don't need to call mCircleDrawable.setBounds(circleDrawableRect) at all.

One additional thing to note from the docs: View#setBackground sets the view's padding to the background's padding. So after calling View#setBackgroundDrawable in DayView#regenerateBackground, you need to call this.setPadding(0,0,0,0); to clear the padding that was applied to the DayView, otherwise the day text will be off center.

jmarr avatar May 07 '20 06:05 jmarr

@jmarr can you explain this ? for code example what i can do?

jrafaelahmedov avatar Jun 16 '20 05:06 jrafaelahmedov

@jrafaelahmedov

code like this as @mogren1158 it works !

@Override protected void onDraw(@NonNull Canvas canvas) { if (customBackground != null) { customBackground.setBounds(tempRect); customBackground.setState(getDrawableState()); customBackground.draw(canvas); } mCircleDrawable.setBounds(circleDrawableRect); mCircleDrawable.setAlpha(255); super.onDraw(canvas); }

private void regenerateBackground() {
    if (selectionDrawable != null) {
        mCircleDrawable.setAlpha(0);
        setBackground(selectionDrawable);
    } else {
        mCircleDrawable = generateBackground(selectionColor, fadeTime, circleDrawableRect);
        mCircleDrawable.setAlpha(0);
        setBackground(mCircleDrawable);
    }
} 

hxkdidi avatar Aug 11 '20 04:08 hxkdidi