Custom TextView Implementation Setting Draable Picture Size

Keywords: Android xml encoding

During the process of developing the project, there have been many difficulties, such as how to realize the four icons in the left personal center bar on the way?

There are probably two ways to solve this problem.
Method 1: A Linear Layout with an Image View and a TextView
Method 2: A TextView and then set drawableLeft

Here are the questions:
Method 1: Big trouble! To write three controls, you need to nest them. If there are more than a few such controls in a row, how many layers of the whole page should be nested? It's too troublesome...

Method 2: This is good. Set drawable Left directly (all four directions are OK). However, the size of this drawable cannot be set by code! And there is no way to reset the image in the code, only in the xml layout file. It's a pit! You can't walk!

This time, I will share a simple custom View with all the old drivers, and go to prosperity and prosperity together!

Come on baby, follow the four steps of customizing View!

Steps to customize View:

1. Properties of custom View
2. Obtain our custom attributes in View's construction method
3. Rewrite onMesure
4. Rewrite onDraw

This time, the custom View inherits from TextView and does not need to recalculate the width, because TextView will help us calculate, which is the benefit of inheriting the control.

Here we go:

1. Properties of custom View

According to requirements, attributes are drawable, drawable width, drawable height, drawable location
Write this in / value/attrs.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <declare-styleable name="MoreTextView">
        <attr name="drawable_src" format="reference"/>
        <attr name="imageHight" format="dimension"/>
        <attr name="imageWidth" format="dimension"/>
        <attr name="imageLocation">
            <enum name="left" value="0"/>
            <enum name="top" value="1"/>
            <enum name="right" value="2"/>
            <enum name="bottom" value="3"/>
        </attr>
    </declare-styleable>
</resources>

2. Obtain our custom attributes in the View's construction method

public class MoreTextView extends TextView {
    public static final int LEFT = 0, TOP = 1, RIGHT = 2, BOTTOM = 3;
    private int mHight, mWidth, mLocation;
    private Bitmap mImage;


    public MoreTextView(Context context) {
        this(context, null);
    }

    public MoreTextView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MoreTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MoreTextView, defStyleAttr, 0);
        int n = a.getIndexCount();
        for (int i = 0; i < n; i++) {
            int attr = a.getIndex(i);
            switch (attr) {

                case R.styleable.MoreTextView_imageWidth:
                    mWidth = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_SP, 0, getResources().getDisplayMetrics()));
                    break;
                case R.styleable.MoreTextView_imageHight:
                    mHight = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_SP, 0, getResources().getDisplayMetrics()));
                    break;
                case R.styleable.MoreTextView_drawable_src:
                    mImage = BitmapFactory.decodeResource(getResources(), a.getResourceId(attr, 0));
                    break;
                case R.styleable.MoreTextView_imageLocation:
                    mLocation = a.getInt(attr, LEFT);
                    break;
            }
        }
        a.recycle();

        drawPicture();//Setting Picture Method


    }
}

Why did you start by saying that this is a very simple custom View? Because there's no need to override the onDraw method, because there's nothing to draw here.

Core methods:

textView.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
//The parameter sub-table represents left, top, right and bottom. Using drawable, null is set without setting

Here is the code for setting drawable:

 private void drawPicture() {
        if (mImage != null) {
            Drawable mDrawable;
            if (mHight != 0 && mWidth != 0) {
                mDrawable = new BitmapDrawable(getResources(), getRealBitmap(mImage));
            } else {
                mDrawable = new BitmapDrawable(getResources(), Bitmap.createScaledBitmap(mImage, mImage.getWidth(), mImage.getHeight(), true));
            }
            switch (mLocation) {
                case LEFT:
                    this.setCompoundDrawablesWithIntrinsicBounds(mDrawable, null,
                            null, null);
                    break;
                case TOP:
                    this.setCompoundDrawablesWithIntrinsicBounds(null, mDrawable,
                            null, null);
                    break;
                case RIGHT:
                    this.setCompoundDrawablesWithIntrinsicBounds(null, null,
                            mDrawable, null);
                    break;
                case BOTTOM:
                    this.setCompoundDrawablesWithIntrinsicBounds(null, null, null,
                            mDrawable);
                    break;
            }

        }


    }

    private Bitmap getRealBitmap(Bitmap image) {
       //Tailor (zoom) Drawable's original size and target width as needed
        int width = image.getWidth();// Get the width and height of the picture
        int height = image.getHeight();
        // Get the matrix parameter you want to scale
        float scaleWidth = (float) mWidth / width;
        float scaleHeight = (float) mHight / height;
        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);
        // Return the new Bitmap
        return Bitmap.createBitmap(image, 0, 0, width, height, matrix, true);

    }

So the Drawable is complete, scaled to the size we want.

  <com.example.captain_shan.myapplication.views.MoreTextView
        android:id="@+id/moreTextview"
        android:layout_marginTop="10dp"
        android:layout_below="@+id/volume"
        android:text="This is a pug dog."
        android:textColor="#ee00ee"
        custom:imageLocation="top"
        android:drawablePadding="5dp"
        custom:imageHight="20dp"
        custom:imageWidth="20dp"
        android:background="#eeeeee"
        custom:drawable_src="@drawable/dog"
        android:layout_width="50dp"
        android:layout_height="50dp"/>

Remember that the root Bureau needs to get a custom space (the name of the space will follow you), the pulse band...

Is it very simple? And the various attributes of TextView can also be used, cool.

Posted by jamesloi on Fri, 29 Mar 2019 09:30:29 -0700