如何更好的通过Inflate layout的方式来实现自定义view
本篇文章讲的是如何用现有控件产生一个组合控件的方法,十分简单实用。现在开始!
一、需求
我们要实现一个有红点和文字的按钮控件,就像下面这样:
二、实现
我的思路是让一个button和一个textview进行组合。
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
> <RadioButton
android:id="@+id/tab_btn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:button="@null"
android:drawablePadding="1dp"
android:gravity="center"
android:textSize="11sp"
/> <TextView
android:id="@+id/tab_hint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:layout_toRightOf="@+id/tab_btn"
android:layout_marginLeft="-5dp"
android:textSize="11sp"
android:minHeight="6dp"
android:singleLine="true" /> </merge>
可以看到最外层我用了merge标签,这是因为我需要把这个xml加载到一个自定义的RelativeLayout中。merge标签主要是用来避免重复嵌套的。
接着我在java代码中加载这个xml文件
public class BottomTab extends RelativeLayout implements BottomTabImpl { public BottomTab(Context context) {
this(context, null);
} public BottomTab(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} public BottomTab(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initViews();
}private void initViews() {
inflate(getContext(), R.layout.test_xml, this);
这样就完成了一个初步的自定义view,但我们要知道merge标签是有弊端的。<merge>标签可以融合其内容,但是不包括自身,因此顶层的属性都丢失了。而且用了merge,在布局中因为不知道最外层是什么控件,所以就不能很好的进行预览。预览的问题无法解决,但是我们有方法让控件最外层的属性加回来。
三、解决merge属性丢失的问题
有三种办法可以将它们添加回来:
1)在代码中添加
private void initViews() {
inflate(getContext(), R.layout.card, this);
// add bg to root view
setBackgroundColor(getResources().getColor(R.color.card_background)); //Add missing top level attributes
int padding = (int)getResources().getDimension(R.dimen.card_padding);
setPadding(padding, padding, padding, padding); ……
}
2)在控件被使用的时候添加丢失的属性
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"> <com.trickyandroid.customview.app.view.Card
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/card_background"
android:padding="@dimen/card_padding" /> </FrameLayout>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="Card">
<attr name="cardStyle" format="reference"/>
</declare-styleable>
</resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
<item name="android:windowBackground">@color/main_background</item>
<item name="cardStyle">@style/CardStyle</item>
</style> <style name="CardStyle" parent="android:Widget.Holo.Light">
<item name="android:padding">@dimen/card_padding</item>
<item name="android:background">@color/card_background</item>
</style> </resources>
public class Card extends RelativeLayout { public Card(Context context) {
super(context, null, R.attr.cardStyle);
init();
} public Card(Context context, AttributeSet attrs) {
super(context, attrs, R.attr.cardStyle);
init();
}
.....
<declare-styleable name="Toolbar">
<attr name="titleTextAppearance" format="reference" />
<attr name="subtitleTextAppearance" format="reference" />
<attr name="title" />
<attr name="subtitle" />
<attr name="android:gravity" />
<attr name="titleMargins" format="dimension" />
<attr name="titleMarginStart" format="dimension" />
<attr name="titleMarginEnd" format="dimension" />
<attr name="titleMarginTop" format="dimension" />
<attr name="titleMarginBottom" format="dimension" />
<attr name="contentInsetStart" />
<attr name="contentInsetEnd" />
<attr name="contentInsetLeft" />
<attr name="contentInsetRight" />
<attr name="maxButtonHeight" format="dimension" />
<attr name="collapseIcon" format="reference" />
<attr name="collapseContentDescription" format="string" />
<attr name="popupTheme" />
<attr name="navigationIcon" format="reference" />
<attr name="navigationContentDescription" format="string" />
<attr name="android:minHeight" />
</declare-styleable>
然后在代码中进行了如下的设置:
public Toolbar(Context context) {
this(context, null);
} public Toolbar(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, R.attr.toolbarStyle);
} public Toolbar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr); // Need to use getContext() here so that we use the themed context
final TintTypedArray a = TintTypedArray.obtainStyledAttributes(getContext(), attrs,
R.styleable.Toolbar, defStyleAttr, 0); mTitleTextAppearance = a.getResourceId(R.styleable.Toolbar_titleTextAppearance, 0);
mSubtitleTextAppearance = a.getResourceId(R.styleable.Toolbar_subtitleTextAppearance, 0);
mGravity = a.getInteger(R.styleable.Toolbar_android_gravity, mGravity);
mButtonGravity = Gravity.TOP;
mTitleMarginStart = mTitleMarginEnd = mTitleMarginTop = mTitleMarginBottom =
a.getDimensionPixelOffset(R.styleable.Toolbar_titleMargins, 0);
这样我们就知道这个view用到了R.attr.toolbarStyle的属性,所以如果我们想要设置一个全局的属性,那么可以在theme中进行设置即可。
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. --> <item name="toolbarStyle">@style/ToolbarStyle</item>
<!--<item name="R.attr.actionOverflowMenuStyle" />--> </style>
设置具体的值:
<style name="ToolbarStyle" parent="Base.Widget.AppCompat.Toolbar">
<item name="titleTextAppearance">@style/TextAppearance.Widget.AppCompat.Toolbar.Title</item>
<item name="subtitleTextAppearance">@style/TextAppearance.Widget.AppCompat.Toolbar.Subtitle</item>
<item name="android:minHeight">?attr/actionBarSize</item>
<item name="titleMargins">0dp</item>
<item name="maxButtonHeight">56dp</item>
<item name="collapseIcon">?attr/homeAsUpIndicator</item>
<item name="collapseContentDescription">@string/abc_toolbar_collapse_description</item>
<item name="contentInsetStart">0dp</item>
<item name="android:minWidth">20dp</item>
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">?attr/actionBarSize</item>
</style>
参考自:http://www.devtf.cn/?p=422
如何更好的通过Inflate layout的方式来实现自定义view的更多相关文章
- 自定义View(7)官方教程:自定义View(含onMeasure),自定义一个Layout(混合组件),重写一个现有组件
Custom Components In this document The Basic Approach Fully Customized Components Compound Controls ...
- 自定义View Layout过程 (3)
目录 目录 1. 知识基础 具体请看我写的另外一篇文章:(1)自定义View基础 - 最易懂的自定义View原理系列 2. 作用 计算View视图的位置. 即计算View的四个顶点位置:Left.To ...
- C#不用union,而是有更好的方式实现 .net自定义错误页面实现 .net自定义错误页面实现升级篇 .net捕捉全局未处理异常的3种方式 一款很不错的FLASH时种插件 关于c#中委托使用小结 WEB网站常见受攻击方式及解决办法 判断URL是否存在 提升高并发量服务器性能解决思路
C#不用union,而是有更好的方式实现 用过C/C++的人都知道有个union,特别好用,似乎char数组到short,int,float等的转换无所不能,也确实是能,并且用起来十分方便.那C# ...
- 【Android - 自定义View】之View的layout过程解析
layout(布局)的作用是ViewGroup用来确定子元素的位置,在这个过程中会用到两个核心方法: layout() 和 onLayout() .layout()方法用来确定View本身的位置,on ...
- 各个浏览器开启CSS Grid Layout的方式
2017年3月,Chrome.Firefox将开启默认支持. 当然对于很多人等不及浏览器默认支持,想提前体验一把,这里提供一些打开方式: 1.Chrome 在浏览器中输入:chrome://flags ...
- 一种更高查询性能的列存储方式MaxMinT 第一部分
简介本文描述了一种列存储方式和对应的查询方法,这种存储方式具有更好的查询性能和更小的存储空间. And查询 本文先用直观的图形方式展示and查询时的方式,这也是算法要解决的问题核心.通常在OLAP数据 ...
- Change Field Layout and Visibility in a List View 在列表视图中更改字段布局和可见性
This lesson will guide you through the steps needed to select columns displayed in the List View. Fo ...
- Android自定义View和控件之一-定制属于自己的UI
照例,拿来主义.我的学习是基于下面的三篇blog.前两是基本的流程,第三篇里有比较细致的绘制相关的属性.第4篇介绍了如何减少布局层次来提高效率. 1. 教你搞定Android自定义View 2. 教你 ...
- android view : 自定义
首先,为什么要使用xml来配置view的视图,这个是mvc的一个思想,你可以把前端和数据分离,可以想一下一个及其复杂的视图假如要修改面对复杂的代码是多么的发愁,xml更明了的表达了视图.然而我们知道a ...
随机推荐
- 帮助你实现漂亮界面的14套免费的 HTML/CSS 源码
在网络上能找很多免费的 PSD 格式素材,但是很少有 HTML/CSS 界面组件下载.在这篇文章中,收集了14套免费的 HTML/CSS 界面源码分享给前端设计师和开发者们.这些组件包括按钮.滑块.表 ...
- oracle表数据类型number对应java中BIgDecimal转int
oracle中id为number类型,在java获取id时用getBigDecimal 相匹配, 如果想转换成int,重写model中的getInt方法: public Integer getInt( ...
- 【JDK源码分析】浅谈HashMap的原理
这篇文章给出了这样的一道面试题: 在 HashMap 中存放的一系列键值对,其中键为某个我们自定义的类型.放入 HashMap 后,我们在外部把某一个 key 的属性进行更改,然后我们再用这个 key ...
- 第3/24周 区_SQL Server中管理空间的基本单位
哇哦,SQL Server性能调优培训已经进入第3周了!同时你已经对SQL Server内核运行机制有了很好的认识.今天我会讲下SQL Server中的区管理,因为这是个很重要的话题,我们会在第23周 ...
- C#自定义特性实例
元数据,就是C#中封装的一些类,无法修改.类成员的特性被称为元数据中的注释. 1.什么是特性 (1)属性与特性的区别 属性(Property):属性是面向对象思想里所说的封装在类里面的数据字段, ...
- 介绍开源的.net通信框架NetworkComms框架 源码分析(十八 ) ConnectionListenerBase
原文网址: http://www.cnblogs.com/csdev Networkcomms 是一款C# 语言编写的TCP/UDP通信框架 作者是英国人 以前是收费的 目前作者已经开源 许可是 ...
- How do you install mysql-connector-python (development version) through pip?
12down votefavorite 8 http://stackoverflow.com/questions/31748278/how-do-you-install-mysql-connector ...
- java servlet手机app访问接口(三)高德地图云存储及检索
这篇关于高德地图的随笔内容会多一点, 一.业务说明 对应APP业务中的成员有两类,一是服务人员,二是被服务人员, 主要实现功能, 对APP中的服务人员位置进行时时定位, 然后通过被服务人员登 ...
- 51Node 1065----最小正子段和
51Node 1065----最小正子段和 N个整数组成的序列a[1],a[2],a[3],…,a[n],从中选出一个子序列(a[i],a[i+1],…a[j]),使这个子序列的和>0,并且这 ...
- 高频sql语句汇总。不断更新。。
操作 语句 创建数据库 CREATE DATABASE dbname/* DEFAULT CHARSET utf8 COLLATE utf8_general_ci;*/ 删除数据库 DROP DATA ...