自定义View系列(五)

    到今天为止,自定义View已经写了四篇了,平时常见的用法比如,自定义控件,自定义布局也都已经介绍的差不多了,今天来看一下通过自定义实现的组合控件,也是自定义View的最后一篇。

    其实组合控件和自定义布局有时候可以达到相同的效果,我们以上一遍自定义View系列(四)中队标题栏为列,通过组合控件来实现。先上代码:

1,自定义TitlBar:

public class TitleBar extends LinearLayout{

    private String mText_content;
    private Context mContext;
    private String mText_left;
    private String mText_right;
    private boolean mShow_left;
    private boolean mShow_right;
    private TextView mTextLeft;
    private TextView mTextRight;
    private TextView mTextTitle;

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

    public TitleBar(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public TitleBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.TitleBar);
        mText_content = typedArray.getString(R.styleable.TitleBar_text_title);
        mText_left = typedArray.getString(R.styleable.TitleBar_text_left);
        mText_right = typedArray.getString(R.styleable.TitleBar_text_right);
        mShow_left = typedArray.getBoolean(R.styleable.TitleBar_show_left,false);
        mShow_right = typedArray.getBoolean(R.styleable.TitleBar_show_right,false);
        typedArray.recycle();

        View line_layout = LayoutInflater.from(mContext).inflate(R.layout.title_layout,this,true);
        mTextLeft = line_layout.findViewById(R.id.text_left);
        mTextRight = line_layout.findViewById(R.id.text_right);
        mTextTitle = line_layout.findViewById(R.id.text_title);
        init();
    }

    private void init() {

       mTextLeft.setVisibility(mShow_left ? VISIBLE:GONE);//判断左边是否显示
        mTextRight.setVisibility(mShow_right ? VISIBLE:GONE);//判断右边是否显示

        if(mText_left != null){
            mTextLeft.setText(mText_left);
        }
        if(mText_right != null){
            mTextRight.setText(mText_right);
        }
        if(mText_content != null){
            mTextTitle.setText(mText_content);
        }
    }
    /** 中间文字大小 */
    public void setTitleSize(int size){
        mTextTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP,size);
    }
    /** 左边文字大小 */
    public void setText_leftSize(int size){
        mTextLeft.setTextSize(TypedValue.COMPLEX_UNIT_PX,size);
    }
    /** 右边文字大小 */
    public void setText_rightSzie(int size){
        mTextRight.setTextSize(size);
    }

    /** 设置左边按钮图片 */
    public void setLeftResource(int resid) {
        Drawable drawable = mContext.getResources().getDrawable(resid);
        drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
        mTextLeft.setCompoundDrawables(drawable, null, null, null);
    }
}

       代码不多,应该非常好理解,首先是titlebar继承了ViewGroup的子类,这里我们以Linearlayout为例;再构造方法中又引入了布局文件,也就是Titlebar的格式(这点和自定义布局不同,自定义布局时,是直接在画布中画出来)。自定义属性中,声明了左边和右边按钮是否显示,和显示内容,以及中间标题的内容。通过初试画init()方法,将声明的自定义属性赋值给Titlebar中的控件,并且暴露(public)了几个方法,以便在代码中设置(这里只随便写了几个方法,只为演示效果。根据个人需要可以增加很多方法,比如点击事件,颜色设置等)。

2,自定义属性:

<!-- 标题栏 -->
<declare-styleable name="TitleBar">
    <attr name="show_left" format="boolean"/>
    <attr name="show_right" format="boolean"/>
    <attr name="text_left" format="string|reference"/>
    <attr name="text_right" format="string|reference"/>
    <attr name="text_title" format="string|reference"/>
</declare-styleable>

3.title_layout的布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="50dp">
    <TextView
        android:id="@+id/text_left"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:gravity="center_vertical"
        android:clickable="true"/>

    <TextView
        android:id="@+id/text_title"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:textSize="26sp"
        android:layout_centerInParent="true"
        android:gravity="center_vertical"/>

    <TextView
        android:id="@+id/text_right"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_alignParentRight="true"
        android:gravity="center_vertical"
        android:clickable="true"
        android:paddingRight="10dp"
        android:paddingLeft="10dp"/>
    
</RelativeLayout>

    从这个xml文件可以看出,标准的头部标题栏模式,两边各有一个可点击的按钮(clickable = true,这个一定要设置,如果不设置,有些华为和小米的机型是不支持TextView的点击事件的),中间是一个页面标题。

4,在看一下调用:

xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <com.example.administrator.myview1.TitleBar
        android:id="@+id/title_bar1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:show_left= "true"
        app:show_right="true"
        app:text_left="返回"
        app:text_right="合同"
        app:text_title="自定义标题栏"/>
    <View
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:background="#FF0000"/>

    <com.example.administrator.myview1.TitleBar
        android:id="@+id/title_bar2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:show_left= "true"
        app:show_right="false"
        app:text_title="自定义标题栏"/>

</LinearLayout>

这个布局文件中,调用了两个Titlebar,中间用一个横线隔开,里面app:后面的属性都已经介绍过了。

看一下在代码页面中的调用:

public class FiveActivity extends AppCompatActivity{

    private TitleBar mTitleBar1;
    private TitleBar mTitleBar2;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.five_layout);
        init();
    }

    private void init() {
        mTitleBar1 = findViewById(R.id.title_bar1);
        mTitleBar1.setText_leftSize(50);//左边位子大小
        mTitleBar1.setText_rightSzie(18);//右边文字大小
        mTitleBar1.setTitleSize(18);//中间文字大小

        mTitleBar2 = findViewById(R.id.title_bar2);
        mTitleBar2.setLeftResource(R.mipmap.icon_black_back);
    }
}

在代码中可以看到,第一个titlebar我们分别设置了文字的大小,第二个titlebar中,我们把左边用图片来显示,右边设置了不显示,运行一下看效果:

                                

很熟悉吧,开发中经常遇见,再一个标题中,我们设置了左边的文字是50,右边和中间的是18,现在是右边和中间的一样,好像都比左边的要打那么一点。明明左边的设置的50更大啊?为什么会这样?我们回到上面的Titlebar中去看,发现

中间文字大小的设置

mTextTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP,size);

左边文字大小的设置:

mTextLeft.setTextSize(TypedValue.COMPLEX_UNIT_PX,size);

右边文字大小的设置:

mTextRight.setTextSize(size);

我们发现前面连个我们都设置了一个属性TypedValue,TypedValue中提供了一些方法TypedValue.applyDimension()方法的功能就是把非标准尺寸转换成标准尺寸。代码中的TypedValue.COMPLEX_UNIT_SP和TypedValue.COMPLEX_UNIT_PX分别表示,我们设置的数值是sp类型的和px类型。不设置时,默认是TypedValue.COMPLEX_UNIT_SP。这样一来,就容易理解了,中间和右边一样,都比左边的要大。第二个titlabr中,我们没有设置中间文字的大小,它取得是title_layout中的默认值30sp。第一个设置了18就是18而不是30,可见代码中设置的优先级要高于xml。 这样子统一设置好之后,当成一个工具类,可以节省很多时间。

关于自定义View的介绍到这里也就结束了。后续可能还会有所更新,也希望有更好建议和理解的道友多多支持和指正!



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值