array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 不用自定义view,放弃使用selector shape - 爱码网

转至 https://blog.csdn.net/qq_25412055/article/details/82598755#commentsedit

前言

作为一个android程序员,对于shape、selector这两个标签一定不陌生。每当UI设计师给我们设计出一个个button背景的时候,我们就需要去drawable文件夹下去新建一个bg_xxx.xml,然后很多时候区别仅仅是一个边框的颜色或者填充的颜色。这就导致了很多非常相似的.xml文件产生。
网上之前也有了一种通过自定义View,在xml中通过设置属性达到shape效果的控件。但是这种自定义的控件不太灵活,归根到底是一个自定义的button,如果我想改造项目的话就得去替换原有的button或者textView。接下来就给大家提供一种更加简单的方式:
无需自定义View,直接添加属性便可以实现shape、selector效果

具体内容

效果展示

话不多说,直接上代码。
使用方法:
1、在BaseActiviy的super.onCreate()之前调用一行代码,仅仅是一个方法

不用自定义view,放弃使用selector shape
2、没有其他操作了,直接layout里开始写控件吧!

布局代码

我们来添加一些实例属性:

不用自定义view,放弃使用selector shape
有没有觉得很熟悉,就是原生标签的tag名+_+属性名,很容易记住,而且不管是Button还是TextView,只要是View都可以。

效果

我们来看一下实际效果:

不用自定义view,放弃使用selector shape

修改背景

现在UI设计师告诉我们要改一下背景,没事,我们只需要在xml添加或者修改属性就行。
我们来把圆形改成正方形,加个边框。5秒ok!

不用自定义view,放弃使用selector shape

简单的原理解析

app:xxx

app:xxx属性就不用多说了,这些就是一些自定义属性而已。在这里我把shape、selector的部分属性转换成自定义的属性,这样就方便添加到已有原生控件中。

BackgroundLibrary.inject(this)

这个方法是这个框架唯一需要加入的代码。
inject中实际上是给LayoutInflater添加了一个LayoutInflater.Factory类。而Android的Activity在创建过程(也就是setContentView)中实际上是通过把xml转换成View的对象。而LayoutInflater.Factory相当于这中间的一个后门,它是xml解析创建成View的必经方法,google中的v7support包里很多内容就是通过LayoutInflater.Factory来实现向下兼容的。
在这里,我通过低入侵的方式,加入一个自定义的LayoutInflater.Factory,去解析添加的自定义属性,接下来就简单了。生成系统提供的GradientDrawable、RippleDrawable、StateListDrawable即可。
同时由于AppcompatActivity是已经实现了LayoutInflater.Factory,而Activity又设定一个Activity只能加入一个factory类,因此这里需要在super.onCreate之前调用该方法,利用AppcompatActivity的factory去创建View。
具体原理解释可以参考我的这篇文章:Android 常用换肤方式以及原理分析

具体使用方法:

添加依赖:

implementation 'com.noober.background:core:1.2.0'
  • 1

BaseActivity的super.onCreate之前添加代码:

BackgroundLibrary.inject(context);
  • 1

支持属性,命名规则就是标签名_标签属性名,支持shape所有属性:

   <attr name="shape" format="enum">
       <enum name="rectangle" value="0" />
       <enum name="oval" value="1" />
       <enum name="line" value="2" />
       <enum name="ring" value="3" />
   </attr>

   <attr name="solid_color" format="color"/>

   <attr name="corners_radius" format="dimension"/>
   <attr name="corners_bottomLeftRadius" format="dimension"/>
   <attr name="corners_bottomRightRadius" format="dimension"/>
   <attr name="corners_topLeftRadius" format="dimension"/>
   <attr name="corners_topRightRadius" format="dimension"/>

   <attr name="gradient_angle" format="integer"/>
   <attr name="gradient_centerX" format="float"/>
   <attr name="gradient_centerY" format="float"/>
   <attr name="gradient_centerColor" format="color"/>
   <attr name="gradient_endColor" format="color"/>
   <attr name="gradient_startColor" format="color"/>
   <attr name="gradient_gradientRadius" format="dimension"/>
   <attr name="gradient_type" format="enum">
       <enum name="linear" value="0" />
       <enum name="radial" value="1" />
       <enum name="sweep" value="2" />
   </attr>
   <attr name="gradient_useLevel" format="boolean"/>

   <attr name="padding_left" format="dimension"/>
   <attr name="padding_top" format="dimension"/>
   <attr name="padding_right" format="dimension"/>
   <attr name="padding_bottom" format="dimension"/>

   <attr name="size_width" format="dimension">
       <enum name="wrap_content" value="-2" />
       <enum name="match_parent" value="-1" />
   </attr>
   <attr name="size_height" format="dimension">
       <enum name="wrap_content" value="-2" />
       <enum name="match_parent" value="-1" />
   </attr>

   <attr name="stroke_width" format="dimension"/>
   <attr name="stroke_color" format="color"/>
   <attr name="stroke_dashWidth" format="dimension"/>
   <attr name="stroke_dashGap" format="dimension"/>

   <!--以下是selector事件-->
   <attr name="ripple_enable" format="boolean"/>
   <attr name="ripple_color" format="color"/>
   <attr name="unpressed_color" format="color"/>
   <attr name="pressed_color" format="color"/>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

例如加一个边框背景,如下即可:

<TextView
    android:layout_width="130dp"
    android:layout_height="36dp"
    android:gravity="center"
    android:text="TextView"
    android:textColor="#8c6822"
    android:textSize="20sp"
    app:corners_radius="4dp"
    app:solid_color="#E3B666"
    app:stroke_color="#8c6822"
    app:stroke_width="2dp" />
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

如果需要selector效果,需要同时添加

app:unpressed_color
app:pressed_color
  • 1
  • 2

如果需要水波纹效果,5.0以上才支持:

app:ripple_enable="true"//打开水波纹开关
app:solid_color="xxx"//设置默认填充颜色
app:ripple_color="xxx"//设置水波纹颜色
  • 1
  • 2
  • 3

注意:
1、如果直接给原生控件添加属性,在xml中会如下报红色异常,这时候不用理会即可。

不用自定义view,放弃使用selector shape
但是红色多了,显示总归难受,可以在根节点添加

tools:ignore="MissingPrefix" 
  • 1

即可

不用自定义view,放弃使用selector shape
2、如果Button设置背景的时候文字显示不全,需要设置padding为0,这是button的系统默认风格导致的。

结尾

项目地址:https://github.com/JavaNoober/BackgroudLibrary
后续更新完善内容会在项目里标明,大家的star是我继续研究的动力☺!

【最新版本已支持selector,详情查看 https://github.com/JavaNoober/BackgroundLibrary

相关文章: