6
\$\begingroup\$

I'd like to have a code review for a component which is supposed to be animatable on its height. It's supposed to be a transitioning element. I find it quite laggy on my phone.

private void init(AttributeSet attrs, int defStyle) {
 // Load attributes
 final TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.GuillotineView, defStyle, 0);
 gradientFirstColor = a.getColor(R.styleable.GuillotineView_gradientFirstColor,Color.RED);
 gradientLastColor = a.getColor(R.styleable.GuillotineView_gradientLastColor, Color.YELLOW);
 maskHeight = a.getDimension(R.styleable.GuillotineView_maskHeight, 10.0f);
 shadowHeight = a.getDimension(R.styleable.GuillotineView_shadowHeight, 20.0f);
 borderRadius = a.getDimension(R.styleable.GuillotineView_borderRadius, 0.0f);
 a.recycle();
 this.refreshGradient();
 this.paint = new Paint();
 this.paint.setFlags(Paint.ANTI_ALIAS_FLAG);
 this.shadowPaint = new Paint();
 this.shadowPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
 setLayerType(LAYER_TYPE_SOFTWARE, this.shadowPaint);
}
private void refreshGradient() {
 this.gd = new GradientDrawable(GradientDrawable.Orientation.TR_BL, new int[]{gradientFirstColor,gradientLastColor});
 this.onSizeChanged(getWidth(), getHeight(), getWidth(), getHeight());
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
 super.onSizeChanged(w, h, oldw, oldh);
 if (getWidth() <= 0 || (getHeight()- Math.round(shadowHeight) <= 0)) {
 return;
 }
 Bitmap gradientBitmap = DrawableExtension.drawableToBitmap(this.gd, getWidth(), getHeight()- Math.round(shadowHeight));
 BitmapShader shader = new BitmapShader(gradientBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
 this.paint.setShader(shader);
 this.path = new Path();
 this.path.moveTo(0,this.borderRadius);
 this.path.lineTo(0,getHeight()-shadowHeight);
 this.path.lineTo(getWidth(),getHeight()-shadowHeight-maskHeight);
 this.path.lineTo(getWidth(),this.borderRadius);
 this.path.arcTo(new RectF(getWidth()-2*borderRadius,0f,(float)getWidth(),2f*borderRadius),0f, -90f);
 this.path.lineTo(borderRadius,0f);
 this.path.arcTo(new RectF(0f,0f,2f*borderRadius,2f*borderRadius),-90f, -90f);
 this.shadowPath = new Path();
 this.shadowPath.moveTo(0, 2 * borderRadius);
 this.shadowPath.lineTo(0, getHeight() - shadowHeight - 1);
 this.shadowPath.lineTo(getWidth(), getHeight() - 1 - shadowHeight - maskHeight);
 this.shadowPath.lineTo(getWidth(), 2 * borderRadius);
 this.shadowPaint.setColor(Color.RED);
 this.shadowPaint.setStyle(Paint.Style.FILL);
 this.shadowPaint.setShadowLayer(shadowHeight + 1, 0, 0, Color.GRAY);
}
// TODO optimize it: it should not have this much computation in the draw method
@Override
protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 if(shadowHeight > 0) {
 canvas.drawPath(shadowPath,this.shadowPaint);
 }
 canvas.drawPath(this.path, paint);
}

This component is used as a shared element within two fragments. its height inside both fragment is different so I can have a transitionning animation.

private void prepareTransitionGuillotine(Fragment fragmentFromTransition, Fragment fragment) {
 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
 ChangeBounds guillotineTransition = new ChangeBounds();
 guillotineTransition.setInterpolator(new OvershootInterpolator(0.5f));
 guillotineTransition.setDuration(700);
 fragment.setSharedElementEnterTransition(guillotineTransition);
 fragment.setSharedElementReturnTransition(guillotineTransition);
 Fade transition = new Fade();
 transition.setDuration(300);
 transition.setInterpolator(new DecelerateInterpolator());
 fragment.setEnterTransition(transition);
 fragmentFromTransition.setExitTransition(transition);
 }
}

It's used like this when pushing a fragment on the screen

prepareTransitionGuillotine(currentFragment, fragment);
manager.beginTransaction().addSharedElement(currentFragment.guillotineView,"guillotineTransition").replace(R.id.fragment_container, fragment).addToBackStack(backstackName).commit();
asked Mar 7, 2017 at 10:11
\$\endgroup\$
7
  • \$\begingroup\$ the draw method is quite efficent there is no need to optimize on that part... how do you know that the onDraw(Canvas canvas) method is the problem? \$\endgroup\$ Commented Feb 13, 2018 at 10:15
  • \$\begingroup\$ I just see the animation flickering that's my only clue on it :) \$\endgroup\$ Commented Feb 13, 2018 at 10:23
  • \$\begingroup\$ onDraw is called only once, when the Activity becomes visible or if you explicitly call invalidate(). so i guess your Activity is somewhere else forced to be redrawn. Can you show us, where you control the drawing? \$\endgroup\$ Commented Feb 13, 2018 at 10:30
  • \$\begingroup\$ yes i know - onDraw can be called on other issues as well (resize, rotate etc).... \$\endgroup\$ Commented Feb 13, 2018 at 10:31
  • 1
    \$\begingroup\$ At least, I presume the change bounds calls the onsizechange on each animation step \$\endgroup\$ Commented Feb 13, 2018 at 11:08

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.