preface

I wrote an article about rounded corners in Android the other day, and two big guys commented on it (thanks guys!!). ShapeableImageView: ShapeableImageView: ShapeableImageView: ShapeableImageView: ShapeableImageView: ShapeableImageView: ShapeableImageView: ShapeableImageView: ShapeableImageView

Introduction to the

The focus of this article is AndroidLayout of the caveThe implementation of the. I’m sure you’ve seen an interface like this

There is a button in the middle, and then the bottomBar just sags down a bit, so it looks very comfortable!! I just want to show you that it works better after tweaking the parameters. This is achieved by MaterialShapeDrawable under the MaterialShapeDrawable package.

parsing

Before starting, it is important to understand that the MaterialShapeDrawable interior is implemented by ShapeAppearanceModel.

ShapeAppearanceModel

/**
 * This class models the edges and corners of a shape, which are used by {@link* MaterialShapeDrawable} to generate and render the shape for a view's background. * MaterialShapeDrawable} Generate and render the shape for a view's background. The MaterialShapeDrawable uses this model to generate and render the background shape of the specified view */
Copy the code

There is also a ShapePathModel which has the same function and has been deprecated.

This class has four CornerTreatment and four EdgeTreatment, which completely describes the background shape of the entire view.

You need to use its built-in Builder to build this object.

CornerTreatment, EdgeTreatment

The implementations of the two classes are remarkably similar. Here’s an inside look at the EdgeTreatment, after all we’re going to use it to describe the path of a depression.

EdgeTreatment

We only need to focus on one method (this class has nothing but three methods), and we can eventually use this method to get the path of this edge, and we can draw any shape we want.

  public void getEdgePath(
      float length, float center, float interpolation, @NonNull ShapePath shapePath) {
    shapePath.lineTo(length, 0);
  }
Copy the code
  1. Length Length of an edge
  2. The distance between the current position of center and the center of the edge (I printed the log and found that the value of center changed after the position was moved, but it was a little bit interesting, I didn’t see it because I wrote the initialization at the beginning of the function, and verified that center == length/2).
  3. I did not use the interpolation parameter. The comment is below

he interpolation of the edge treatment. Ranges between 0 (none) and 1 (fully) interpolated. Custom edge treatments can implement interpolation to support shape transition between two arbitrary states. Typically, a value of 0 indicates that the custom edge treatment is not rendered (i.e. that it is a straight line), and a value of 1 indicates that the treatment is fully rendered. Animation between these two values can “heal” or “reveal” an edge treatment. Interpolation edge processing interpolation. Interpolation range between 0 (none) and 1 (complete). Custom edge processing implements interpolation to support shape * transitions between two arbitrary states. In general, a value of 0 indicates that custom edge processing is not rendered (that is, it is a straight line), and a value of 1 indicates that the processing is fully rendered. An animation between these two values can “fix” or “show” edge processing.

  1. ShapePath Our description of this edge just goes to that path

MaterialShapeDrawable

The MaterialShapeDrawable inherits from Drawable so it can be set directly on any view.

One of its constructers is to receive a ShapeAppearanceModel object directly

 / * * *@param shapeAppearanceModel the {@link ShapeAppearanceModel} containing the path that will be
   *     rendered in this drawable.
   */
  public MaterialShapeDrawable(@NonNull ShapeAppearanceModel shapeAppearanceModel) {}
Copy the code

Of course, you can also set a Model object directly

  @Override
  public void setShapeAppearanceModel(@NonNull ShapeAppearanceModel shapeAppearanceModel) {}
Copy the code

practice

Train of thought

  1. To create aShapeAppearanceModelObject, set the path of the topEdge object,
  2. Use this object to generate oneMaterialShapeDrawableobject
  3. Set drawable to the background of the view

code

val bar = findViewById<LinearLayout>(R.id.bar)
val shapePathModel = ShapeAppearanceModel
.Builder()
.setTopEdge(object: EdgeTreatment(){
      override fun getEdgePath(
          length: Float,
          center: Float,
          interpolation: Float,
          shapePath: ShapePath
 ) {
       // Radius of the depression
       val r = length/10 // == center
       val halfLine = length/2-r
       // The larger the value, the smoother the corner, but must be less than or equal to r, this size can be tried more
       val offset = 30f 
       // The first part, the line, is drawn to the beginning of the depression
       shapePath.lineTo(halfLine-offset,0f)
       // The corner at the beginning of the depression looks sharp if left untreated
       shapePath.quadToPoint(halfLine,0f,halfLine+offset,offset)
       // The sunken part
       shapePath.quadToPoint(center,r,halfLine+2*r-offset,offset)
       // The corner where the depression ends
       shapePath.quadToPoint(halfLine+2*r,0f,halfLine+2*r+offset,0f)
       // The last part of the line, let me draw it to the end
       shapePath.lineTo(length,0f)
    }
}).build()

val drawable = MaterialShapeDrawable(shapePathModel)
bar.background = drawable
// This is the end
Copy the code

conclusion

There is no end to learning!!

Thank you for your sharing, and let me learn a wave 👍!

Come on!!

If there is any mistake, please inform me in time. I will correct it immediately. I also welcome your suggestions.