自定义组件(四)

来源:互联网 发布:js url encode 解码 编辑:程序博客网 时间:2024/06/11 14:57

重写onMeasure(int widthMeasureSpec, int heightMeasureSpec) 和
onDraw(Canvas canvas)方法生成自定义view


效果图
这里写图片描述


在values文件夹下新建textview_attr.xml文件
定义自定义布局的属性

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="MyTextView">        <attr name="textSize" format="integer"></attr>        <attr name="text" format="string|reference"></attr>        <attr name="textColor" format="color|reference"></attr>        <attr name="underLine" format="boolean"></attr>    </declare-styleable></resources>

创建MyTextView继承View
实现前三个构造方法

  public MyTextView(Context context) {        super(context);        init();    }    public MyTextView(Context context, AttributeSet attrs) {        super(context, attrs);        getAttr(attrs);        init();    }    public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        getAttr(attrs);        init();    }

初始化属性值

   //初始化属性值    private int textSize =36;    private int textColor = Color.BLACK;    private String text ="Hello World";    private boolean underLine =false;

初始化画笔和定位距离的变量

//初始化画笔属性    private Paint textpaint;    private  int left,top;

给定义的变量设置set方法

public void setTextSize(int textSize) {        this.textSize = textSize;    }    public void setTextColor(int textColor) {        this.textColor = textColor;    }    public void setText(String text) {        this.text = text;     }     public void setUnderLine(boolean underLine) {        this.underLine = underLine;    }

获取属性值

//获取属性值    public void getAttr (AttributeSet attrs){        TypedArray type=getContext().obtainStyledAttributes(attrs,R.styleable.MyTextView);        textSize=type.getInt(R.styleable.MyTextView_textSize,textSize);        textColor=type.getColor(R.styleable.MyTextView_textColor,textColor);        text=type.getString(R.styleable.MyTextView_text);        underLine=type.getBoolean(R.styleable.MyTextView_underLine,underLine);        type.recycle();    }

给画笔设置初始值

    public void init(){        textpaint=new Paint();        textpaint.setTextSize(textSize);        textpaint.setColor(textColor);        textpaint.setUnderlineText(underLine);    }

重写onMeasure方法,计算并且设置宽高

   @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        int width=calWidth(widthMeasureSpec);        int height=calHeight(heightMeasureSpec);        setMeasuredDimension(width,height);    }

计算宽

 private int calWidth(int widthMeasureSpec) {        int widthMode=MeasureSpec.getMode(widthMeasureSpec);        int widthSize=MeasureSpec.getSize(widthMeasureSpec);        int widthText= (int) textpaint.measureText(text);        int width=widthText;        left=getPaddingLeft();        if(widthMode==MeasureSpec.EXACTLY){            width=widthSize;        }        if(widthMode==MeasureSpec.AT_MOST){            width=Math.min(widthSize,widthText);        }        return width+getPaddingLeft()+getPaddingRight();    }

计算高

 private int calHeight(int heightMeasureSpec) {        int heightMode=MeasureSpec.getMode(heightMeasureSpec);        int heightSize=MeasureSpec.getSize(heightMeasureSpec);        int heightText= (int) (-textpaint.getFontMetrics().top+textpaint.getFontMetrics().bottom);        int height=heightText;        top= (int) (-textpaint.getFontMetrics().top+getPaddingLeft());        if(heightMode==MeasureSpec.EXACTLY){            height=heightSize;        }        if(heightMode==MeasureSpec.AT_MOST){            height=Math.min(heightSize,heightText);        }        return height+getPaddingTop()+getPaddingBottom();    }

重写onDraw方法,在画布上用画笔绘制

   @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        canvas.drawColor(Color.LTGRAY);        canvas.drawText(text,left,top,textpaint);    }

在set方法下添加刷新方法

public void setText(String text) {        this.text = text;        //从新绘制布局        requestLayout();        //刷新界面        invalidate();    }

在布局中添加自定义View

 <com.axnet.temp0728.MyTextView        android:id="@+id/main_tv"        android:padding="20dp"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        app:underLine="true"        app:textSize="72"        app:text="hello world"        app:textColor="#00cacb"        />

在布局中添加自定义属性的定义空间

 xmlns:app="http://schemas.android.com/apk/res-auto"

自定义布局中就可以使用,我们定义的属性

   app:textSize="72"        app:text="hello world"        app:textColor="#00cacb"

mainActivity的代码,改变自己定义的View的变化

  button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                main_tv.setText("666");                main_tv.setUnderLine(false);            }        });

全部代码
mainActivity

public class MainActivity extends AppCompatActivity {    Button button;    MyTextView main_tv;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        button=(Button)findViewById(R.id.button);        main_tv=(MyTextView)findViewById(R.id.main_tv);        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                main_tv.setText("666");                main_tv.setUnderLine(false);            }        });    }}

mainActivity的布局

<?xml version="1.0" encoding="utf-8"?><LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:id="@+id/activity_main"    android:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="com.axnet.temp0728.MainActivity">    <Button        android:text="点击更换文字"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:id="@+id/button"/>    <com.axnet.temp0728.MyTextView        android:id="@+id/main_tv"        android:padding="20dp"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        app:underLine="true"        app:textSize="72"        app:text="hello world"        app:textColor="#00cacb"        /></LinearLayout>

MyTextView

public class MyTextView extends View{    //初始化属性值    private int textSize =36;    private int textColor = Color.BLACK;    private String text ="Hello World";    private boolean underLine =false;    //初始化画笔属性    private Paint textpaint;    private  int left,top;    public void setTextSize(int textSize) {        this.textSize = textSize;    }    public void setTextColor(int textColor) {        this.textColor = textColor;    }    public void setText(String text) {        this.text = text;        //从新绘制布局        requestLayout();        //刷新界面        invalidate();    }    public void setUnderLine(boolean underLine) {        this.underLine = underLine;        //从新绘制布局        requestLayout();        //刷新界面        invalidate();    }    public MyTextView(Context context) {        super(context);        init();    }    public MyTextView(Context context, AttributeSet attrs) {        super(context, attrs);        getAttr(attrs);        init();    }    public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        getAttr(attrs);        init();    }    //获取属性值    public void getAttr (AttributeSet attrs){        TypedArray type=getContext().obtainStyledAttributes(attrs,R.styleable.MyTextView);        textSize=type.getInt(R.styleable.MyTextView_textSize,textSize);        textColor=type.getColor(R.styleable.MyTextView_textColor,textColor);        text=type.getString(R.styleable.MyTextView_text);        underLine=type.getBoolean(R.styleable.MyTextView_underLine,underLine);        type.recycle();    }    public void init(){        textpaint=new Paint();        textpaint.setTextSize(textSize);        textpaint.setColor(textColor);        textpaint.setUnderlineText(underLine);    }    //计算并设置宽高// widthMeasureSpec heightMeasureSpec  宽高规则    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        int width=calWidth(widthMeasureSpec);        int height=calHeight(heightMeasureSpec);        setMeasuredDimension(width,height);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        canvas.drawColor(Color.LTGRAY);        canvas.drawText(text,left,top,textpaint);    }    private int calHeight(int heightMeasureSpec) {        int heightMode=MeasureSpec.getMode(heightMeasureSpec);        int heightSize=MeasureSpec.getSize(heightMeasureSpec);        int heightText= (int) (-textpaint.getFontMetrics().top+textpaint.getFontMetrics().bottom);        int height=heightText;        top= (int) (-textpaint.getFontMetrics().top+getPaddingLeft());        if(heightMode==MeasureSpec.EXACTLY){            height=heightSize;        }        if(heightMode==MeasureSpec.AT_MOST){            height=Math.min(heightSize,heightText);        }        return height+getPaddingTop()+getPaddingBottom();    }    private int calWidth(int widthMeasureSpec) {        int widthMode=MeasureSpec.getMode(widthMeasureSpec);        int widthSize=MeasureSpec.getSize(widthMeasureSpec);        int widthText= (int) textpaint.measureText(text);        int width=widthText;        left=getPaddingLeft();        if(widthMode==MeasureSpec.EXACTLY){            width=widthSize;        }        if(widthMode==MeasureSpec.AT_MOST){            width=Math.min(widthSize,widthText);        }        return width+getPaddingLeft()+getPaddingRight();    }}

自定义属性的textview_attr 在 values目录下

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="MyTextView">        <attr name="textSize" format="integer"></attr>        <attr name="text" format="string|reference"></attr>        <attr name="textColor" format="color|reference"></attr>        <attr name="underLine" format="boolean"></attr>    </declare-styleable></resources>

自定义布局感觉还是不是掌握的很好,最近吧课程学完了,准备学一下
HenCoder的自定义View
http://hencoder.com/
不会使用的东西还有很多,会使用但是不知道实现原理的东西更多
加油