`
445822357
  • 浏览: 731082 次
文章分类
社区版块
存档分类
最新评论

Android自定义带标题边框的Layout

 
阅读更多

今天工作中又碰到个小问题,项目需要用到像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>

下面是效果图:



分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics