How to create a custom View?
- The View is first inherited and then written to the layout
public class CircleLoadingView extends View { private Paint paint; public CircleLoadingView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); paint = new Paint(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int radius = DpPxUtils.dp2px(80); Canvas. Methods like drawCircle (0, 0, the radius, paint); }}Copy the code
2. Then write it to the layout
<LinearLayout
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.smallcake.template.custom.CircleLoadingView
android:background="@color/red"
android:layout_width="100dp"
android:layout_height="100dp"/>
</LinearLayout>
Copy the code
3. Run and the effect comes out
Note:
1. Custom View constructor is a two-parameter constructor, do not write ratio error 2. Paint is best written by default because onDraw may be executed multiple times and the brush defaults to black
How to get the width and height of a custom View?
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
}
Copy the code
Or: onDraw() via getWidth() and getHeight()
Note:
- 1.
onMeasure
The method is executed three times - 2. Understand first
MeasureSpec
There are three modes:UNSPECIFIED,AT_MOST,EXACTLY
- 3.
int
Type ofMeasureSpec
To represent the size of a component, this variable contains not only the size of the component, but also the size of the mode, a total of 32 bits, the first two bits to mark the mode, the last 30 bits to mark the space size - 4. In general, we often see this when we are customizing views
AT_MOST
和EXACTLY
.UNSPECIFIED
This pattern is applied to the system source code. Such asNestedScrollView
和ScrollView
- 5. How to obtain the corresponding mode:
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
Reference: www.cnblogs.com/liushilin/p…
model | describe | The corresponding |
---|---|---|
Precision Mode 01 (MeasureSpec.EXACTLY ) |
In this mode, the component is as long or wide as the value of size. | The correspondingMATCH_PARENT 和To determine the value of the . |
Maximum Mode 11 (MeasureSpec.AT_MOST ) |
So this is the parent component, the maximum amount of space that can be given, and the current component can only be as large or as wide as this, but it can also be smaller than this. | The corresponding WRAP_CONETNT |
Mode 00 not specified (MeasureSpec.UNSPECIFIED ) |
This means that the current component can use whatever space it wants. | all |
Three. Some style Settings?
The effect | code |
---|---|
anti-aliasing | paint.setAntiAlias(true); |
hollow | paint.setStyle(Paint.Style.STROKE); |
Line width | paint.setStrokeWidth(8); |
What is the difference between RectF and Rect?
- 1. They are both used to construct a rectangular area
- 2. The precision is different. Rect uses int as a value, RectF uses float as a value
- 3. The methods provided by the two types are not identical. For example, RectF(Rect R) constructs a RectF object based on the given Rect object, thus extending the functions that Rect does not have
5. Draw circles
canvas.drawCircle(float cx, float cy, float radius, @NonNull Paint paint)
Copy the code
- 1. Paint from the center of the brush. If the brush thickness is too wide, it will appear up, down, left and right
A less
, we should set the radiusRadius - Brush group thick /2
Draw an arc
RectF rectF = new RectF(0, 0, width, height); Canvas. DrawArc (rectF, 0, 30, false, paint);Copy the code
DrawArc parameters :1. draw area, 2. start Angle, 3. end Angle, 4. Whether to connect center point, 5, brush
- 1. If you want to draw an arc, not an arc section, set the brush style to hollow
paint.style = Paint.Style.STROKE
- Demo: Draw an arc of loading progress, and combine animation, let it move
class CircleLoaindView : View { private val paint = Paint() private val paint2 = Paint() private var rectF: RectF? = null private var position = 0 private val paintWidth = 4f// Constructor (context: context? , attrs: AttributeSet?) : super(context, attrs) { paint.setColor(Color.parseColor("#DDDDDD")) paint.isAntiAlias = true paint.style = Paint.Style.STROKE paint.strokeWidth = paintWidth paint2.setColor(Color.parseColor("#535353")) paint2.isAntiAlias = true paint2.style = Paint.Style.STROKE paint2.strokeWidth = paintWidth paint2.strokeCap = Paint.Cap.ROUND } fun setPosition(position: Int) { this.position = position; invalidate() } override fun onDraw(canvas: Canvas?) { super.onDraw(canvas) val centerX = width / 2 val strokeWidth = centerX / radius canvas? .let {// draw the gray background circle canvas.drawcircle ((width / 2).tofloat (), (height / 2).tofloat (), (width / 2).toFloat() - paintWidth / 2, If (rectF == null) rectF = rectF ((strokeWidth / 2).tofloat () + paintWidth / 2, (strokeWidth / 2).toFloat() + paintWidth / 2, (2 * centerX - strokeWidth / 2).toFloat() - paintWidth / 2, (2 * Centerx-strokeWidth / 2).tofloat () -paintwidth / 2) // Draw the arc section canvas.drawarc (rectF!! , 3.6f * position, 360f / 30, false, paint2)}}}Copy the code
<com.smallcake.test.CircleLoaindView
android:id="@+id/circleLoading"
android:layout_width="200dp"
android:layout_height="200dp"
/>
Copy the code
val animator: ObjectAnimator = ObjectAnimator.ofInt(circleLoading, "position", 0, 100)
animator.duration = 1000
animator.repeatCount = Animation.INFINITE
animator.interpolator = LinearInterpolator()
animator.start()
Copy the code