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>


下面是效果图:

 

Android自定义带标题边框的Layout

 

你可能感兴趣的:(android)