No trivial interface (a): RecyclerView+CardView to know

No trivial interface (two): RecyclerView to show more different views

Interface no trivial (three): RecyclerView + Toolbar to make a file selector

Interface no small matter (4): write a scroll selector!

Interface no small matter (five): custom TextView

Interface no small matter (six): to make a good-looking side pull menu!

Making portal


directory

  • rendering
  • preface
  • Custom attributes
  • MeasureSpec class
  • Color resolution
  • Font size conversion
  • The last

rendering

Without further ado, go straight to the picture above and read more if you’re interested.


preface

When I wrote the fourth scroll selector, I was vague about the custom view area, something was not clear, this time I will fill in the custom view area.


Custom attributes

One of the highlights of custom views is adding custom properties. Here we fill in the three usual ones, text, color, and size. It can then be used in the layout file. Finally, the attributes are obtained and assigned in the custom class.

<? xml version="1.0" encoding="utf-8"? > <resources> <declare-styleable name="MyTextView">
        <attr name="text" format="string" />
        <attr name="color" format="color" />
        <attr name="size" format="dimension" />
    </declare-styleable>
</resources>
Copy the code
xmlns:app="http://schemas.android.com/apk/res-auto"
Copy the code
<com.so.mytextview.ui.view.MyTextView
    android:id="@+id/mtv_test"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    app:color="@color/colorAccent"
    app:size="60sp"
    app:text="hello world" />
Copy the code
public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs); } private void init(Context context, AttributeSet attrs) {/ / access to custom properties TypedArray ta = context. ObtainStyledAttributes (attrs, R.s tyleable. MyTextView); mSize = ta.getDimension(R.styleable.MyTextView_size, 16); mText = ta.getString(R.styleable.MyTextView_text); mColor = ta.getColor(R.styleable.MyTextView_color, Color.BLACK); ta.recycle(); // Set paintbrush mPaint = new Paint(paint.anti_alias_flag); mPaint.setTextSize(mSize); // Set the background Color mBkColor = color.blue; }Copy the code

MeasureSpec class

MeasureSpec The most important thing about the onMeasure method is the use of MeasureSpec. Match_parent and wrap_content are EXACTLY the same. Wrap_content is AT_MOST. The ScrollView or ListView will be UNSPECIFIED.

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int width = 0;
    int height = 0;

    int specMode = MeasureSpec.getMode(widthMeasureSpec);
    int specSize = MeasureSpec.getSize(widthMeasureSpec);

    switch (specMode) {
        case MeasureSpec.EXACTLY:
            width = getPaddingLeft() + getPaddingRight() + specSize;
            break;

        case MeasureSpec.AT_MOST:
        case MeasureSpec.UNSPECIFIED:
            width = (int) (getPaddingLeft() + getPaddingRight()
                    + mPaint.measureText(mText));
            break;
    }

    specMode = MeasureSpec.getMode(heightMeasureSpec);
    specSize = MeasureSpec.getSize(heightMeasureSpec);

    switch (specMode) {
        case MeasureSpec.EXACTLY:
            height = getPaddingTop() + getPaddingBottom() + specSize;
            break;

        case MeasureSpec.AT_MOST:
        case MeasureSpec.UNSPECIFIED:
            Paint.FontMetrics fmi = mPaint.getFontMetrics();
            float textHeight = Math.abs(fmi.bottom - fmi.top);
            height = (int) (getPaddingTop() + getPaddingBottom() + textHeight);
            break;
    }

    setMeasuredDimension(width, height);
}
Copy the code

The two main points are to calculate the width and height of the string, using the measureText method of the Paint instance. Height refers to the Paint.FontMetrics class I wrote in article 4, which takes the absolute value of the bottom minus the top.


Color resolution

Color is the class to deal with. When you get the function with getColor, it is an int. If we need to change the Color again, we need to parse the int and restore it to RGB.

/** * get RGB values based on color values ** @param color color values * @returnRGB value */ public int[]setColor(int color) {
    int[] rgb = new int[3];
    rgb[0] = (color & 0x00ff0000) >> 16;
    rgb[1] = (color & 0x0000ff00) >> 8;
    rgb[2] = (color & 0x000000ff);
    return rgb;
}
Copy the code

Font size conversion

The most important thing to do with font size is to convert it. Px is used in code, but SP is used in layout files.

/** * public static int sp2px()float spVal) {
    return(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal, getContext().getResources().getDisplayMetrics()); } /** * px to sp */ public staticfloat px2sp(float pxVal) {
    return (pxVal / getContext().getResources().getDisplayMetrics().scaledDensity);
}
Copy the code

The last

This allows you to customize some simple view classes, but more complex ones need to handle more arguments, especially the four-argument constructor. If you have any comments or suggestions, please feel free to like or follow me in the comments section