Android自定义带标题边框的Layout

时间:2022-08-26 21:28:31

今天工作中又碰到个小问题,项目需要用到像Java Swing的JPanel一样带标题边框的布局,Android里没有类似控件,想到这个也不难,自己画了一个,是继承LinearLayout的一个自定义布局,当然,可以根据需要继承其他布局,基本都是一样的过程。

当然这个自定义布局有点瑕疵,就是标题占用了布局的一部分高度,子控件需要调整在布局中的垂直位置来避免和标题边框靠得过紧。

------------------本博客如未明正声明转载,皆为原创,转载请注明出处!------------------

下面贴代码:

/**
* 一个像java swing的JPanel控件一样可以带标题边框的布局,可以指定标题位置、颜色、字体大小。
* 另外还可以控制边框大小和边框的颜色。但是,子控件指定垂直布局适应的时候,子控件看起来并不在布局中间,
* 因为标题高度占用了布局的一部分垂直空间,使用时子控件需要指定Margin Top,否则可能和标题重叠。
*
* This is a layout with title border, you can set a title just like Java-Swing JPanel.
* and you can control the position, the color and the size of the title. In addition,
* the border's color and size are always controlled.
*
* !FIXME: The title has its own height, so when the children's gravity set as {@link Gravity#CENTER}
* or {@link Gravity#CENTER_VERTICAL} do not work well.
*
* @date 2013/09/24
* @author Wison
*/
public class TitleBorderLayout extends LinearLayout { /** 默认情况下标题在总长度的1/10处显示 */
private static float DEFAULT_TITLE_POSITION_SCALE = 0.1f;
public static int DEFAULT_BORDER_SIZE = 1;
public static int DEFAULT_BORDER_COLOR = Color.GRAY;
public static int DEAFULT_TITLE_COLOR = Color.BLACK; /** 边框面板的高度 */
private int mBorderPaneHeight ; private Paint mBorderPaint;
private float mBorderSize; private TextPaint mTextPaint;
private CharSequence mTitle;
private int mTitlePosition; public TitleBorderLayout(Context context) {
this(context, null);
} /**
* Construct a new TitleBorderLayout with default style, overriding specific style
* attributes as requested.
* @param context
* @param attrs
*/
public TitleBorderLayout(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(false); mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
Resources res = getResources();
mTextPaint.density = res.getDisplayMetrics().density; TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TitleBorderLayout); mTitle = a.getText(R.styleable.TitleBorderLayout_title);
int titleColor = a.getColor(R.styleable.TitleBorderLayout_titleTextColor, DEAFULT_TITLE_COLOR);
mTextPaint.setColor(titleColor); float titleTextSize = a.getDimension(R.styleable.TitleBorderLayout_titleTextSize, 0);
if (titleTextSize > 0) {
mTextPaint.setTextSize(titleTextSize);
} mTitlePosition = a.getDimensionPixelSize(R.styleable.TitleBorderLayout_titlePosition, -1); mBorderSize = a.getDimensionPixelSize(R.styleable.TitleBorderLayout_borderSize, DEFAULT_BORDER_SIZE); int borderColor = a.getColor(R.styleable.TitleBorderLayout_borderColor, DEFAULT_BORDER_COLOR);
mBorderPaint.setColor(borderColor); a.recycle();
} /**
* Get the color of border.
* @return
*/
public int getBorderColor() {
return mBorderPaint.getColor();
} /**
* Set the color of border.
* @param borderColor
*/
public void setBorderColor(int borderColor) {
mBorderPaint.setColor(borderColor);
requestLayout();
} /**
* Get the size of border.
* @return
*/
public float getBorderSize() {
return mBorderSize;
} /**
* Set the size of border.
* @param borderSize
*/
public void setBorderSize(float borderSize) {
mBorderSize = borderSize;
requestLayout();
} /**
* Get the color of title.
* @return
*/
public int getTitleColor() {
return mTextPaint.getColor();
} /**
* Set the color of title.
* @param titleColor
*/
public void setTitleColor(int titleColor) {
mTextPaint.setColor(titleColor);
requestLayout();
} /**
* Get the size of title.
* @return
*/
public float getTitleTextSize() {
return mTextPaint.getTextSize();
} /**
* Set the size of title.
* @param titleTextSize
*/
public void setTitleTextSize(float titleTextSize) {
mTextPaint.setTextSize(titleTextSize);
requestLayout();
} /**
* Get the title.
* @return
*/
public CharSequence getTitle() {
return mTitle;
} /**
* Set the title which will be shown on the top of border pane.
* @param title
*/
public void setTitle(CharSequence title) {
mTitle = title;
requestLayout();
} /**
* Get the position of title.
* @return
*/
public int getTitlePosition() {
return mTitlePosition;
} /**
* Set the position of title where the paint will start to draw.
* @param titlePosition
*/
public void setTitlePosition(int titlePosition) {
mTitlePosition = titlePosition;
requestLayout();
} /**
* Get the height of border pane, it's different from the layout height!
* @return
*/
public int getBorderPaneHeight() {
return mBorderPaneHeight;
} /**
* Draw the title border
* @param canvas
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas); FontMetrics fm = mTextPaint.getFontMetrics();
final float titleHeight = fm.descent - fm.ascent; final CharSequence titleText = (mTitle == null) ? "" : mTitle;
final float titleWidth = Layout.getDesiredWidth(titleText, mTextPaint); final int width = getWidth();
final int height = getHeight(); if (mTitlePosition <= 0 || mTitlePosition + titleWidth > width) {
mTitlePosition = (int) (DEFAULT_TITLE_POSITION_SCALE * width);
} final float topBorderStartY = titleHeight / 3f - mBorderSize / 2; mBorderPaneHeight = (int) Math.ceil(height - topBorderStartY);
/* 画标题边框 */
// 上
canvas.drawRect(0, topBorderStartY, mTitlePosition, topBorderStartY + mBorderSize, mBorderPaint);
canvas.drawText(titleText.toString(), mTitlePosition, titleHeight / 3 * 2f, mTextPaint); // 标题
canvas.drawRect(mTitlePosition + titleWidth, topBorderStartY, width, topBorderStartY + mBorderSize, mBorderPaint);
// 左
canvas.drawRect(0, topBorderStartY, mBorderSize, height, mBorderPaint);
// 右
canvas.drawRect(width - mBorderSize, topBorderStartY, width, height, mBorderPaint);
// 下
canvas.drawRect(0, height - mBorderSize, width, height, mBorderPaint);
} }

以下为属性声明:

    <declare-styleable name="TitleBorderLayout">
<!-- The title of BorderTitleLayout. -->
<attr name="title" format="string" />
<!-- The size of title. -->
<attr name="titleTextSize" format="dimension" />
<!-- The title start postion. -->
<attr name="titlePosition" format="dimension" />
<!-- The color of title. -->
<attr name="titleTextColor" format="reference|color" />
<!-- The size of border. -->
<attr name="borderSize" format="dimension" />
<!-- The color of border. -->
<attr name="borderColor" format="reference|color" />
</declare-styleable>

下面是效果图:

Android自定义带标题边框的Layout

Android自定义带标题边框的Layout的更多相关文章

  1. Android 自定义带刻度的seekbar

    自定义带刻度的seekbar 1.布局 <span style="font-family:SimHei;font-size:18px;"><com.imibaby ...

  2. Android -- 自定义带进度条的按钮

    1. 实现了一个带进度条的按钮,完成后显示提示信息,并设置按钮为不可再次被点击

  3. Android自定义EditText去除边框并添加下划线

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

  4. Android 自定义带回调的Dialog 及EditText相关

      import android.app.Activity; import android.content.Context; import android.text.Editable; import ...

  5. android自定义圆角实线边框,圆角虚线边框,直实线,虚实线,半圆角边框

    先上图 在现实项目开发中,单纯的Button,EditText等控件远远不能满足我们项目的UI设计需求,这时候,我们就需要自己动手丰衣足食啦.接下来先给大家介绍一些属性,备注写的都非常清楚啦,我就不啰 ...

  6. Android实现自定义带文字和图片的Button

    Android实现自定义带文字和图片的Button 在Android开发中经常会需要用到带文字和图片的button,下面来讲解一下常用的实现办法. 一.用系统自带的Button实现 最简单的一种办法就 ...

  7. &lbrack;转&rsqb;Android UI&colon;看看Google官方自定义带旋转动画的ImageView-----RotateImageView怎么写&lpar;附 图片淡入淡出效果&rpar;

    http://blog.csdn.net/yanzi1225627/article/details/22439119 众所周知,想要让ImageView旋转的话,可以用setRotation()让其围 ...

  8. 我的Android进阶之旅------>Android自定义View实现带数字的进度条(NumberProgressBar)

    今天在Github上面看到一个来自于 daimajia所写的关于Android自定义View实现带数字的进度条(NumberProgressBar)的精彩案例,在这里分享给大家一起来学习学习!同时感谢 ...

  9. Android自定义控件 -- 带边框的TextView

    使用xml实现边框 原来使用带边框的TextView时一般都是用XML定义来完成,在drawable目录中定义如下所示的xml文件: <?xml version="1.0" ...

随机推荐

  1. trunk 的坑

    三层交换机A和三层交换机B之间原本配置有trunk口,如再用trunk连二层交换机会导致环路,网络不通.将L3 A和L3-B之间断开正常.

  2. 让Chrome支持Ajax&sol;&dollar;http方式读取本地文件

    在开发中经常写些小demo调试一下插件什么的 数据源又经常手动构造分离为一个单独的文件.用ajax或$http去访问时总是拒绝访问.这个时候可以给Chrome的快捷图标加启动参数,让浏览器允许js访问 ...

  3. HDU-4689 Derangement DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4689 题意:初始序列1,2...n,求所有满足与初始序列规定大小的错排数目.. 这道题目感觉很不错~ ...

  4. PowerShell随笔2&lowbar;分支 选择 循环 特殊变量

    PowerShell特殊变量: PowerShell的特殊变量由系统自动创建.用户自定义的变量名称应该不和特殊变量相同. $^ :前一命令行的第一个标记 $$ :前一命令行的最后一个标记 $_ :表示 ...

  5. Jquery学习(三)选择

    1.Jquery最重要的是选择. 学习要点:        1.简单选择器        2.进阶选择器        3.高级选择器 ①简单选择器. 最简单的也就是最经常使用的,最经常使用的一般也是 ...

  6. SpringMVC框架学习笔记(6)——拦截器

    SpringMVC拦截器需要实现接口HandlerInterceptor 有3个方法,分别在请求处理前.请求处理后和在DispatcherServlet处理后执行 实现代码: package inte ...

  7. python之常用模块

    python 常用模块 之 (subprocess模块.logging模块.re模块) python 常用模块 之 (序列化模块.XML模块.configparse模块.hashlib模块) pyth ...

  8. JS AJAX 跨域

    原因: 浏览器的同源策略,不允许AJAX 访问 其他接口 协议,域名,端口 一个不同 就跨域了  http 端口(80) https(443) 可以跨域的三个标签: 1. img : 打点统计,没有浏 ...

  9. 023 Spark Scheduler(调度)

    1.官网 http://spark.apache.org/docs/1.6.1/job-scheduling.html http://spark.apache.org/docs/1.6.1/confi ...

  10. python2&period;0&lowbar;s12&lowbar;day12&lowbar;html介绍

    html 就像一个裸体的人css 就像是人穿的衣服js 就像是人做的动作一.网页文件HTML的构成 1.对应规则的选择,就如同我们写python时#!/usr/bin/env python3.5 这么 ...