Android-自定义显示价格的PriceView

转载请标明出处:http://blog.csdn.net/goldenfish1919/article/details/44418883

先看一下我们要做的效果:

价格分成了3部分,前面是一个¥,中间的整数部分,后面的小数部分,中间还带一个删除线。

参考:http://blog.csdn.net/lmj623565791/article/details/44098729,我们这个其实更简单,自定义一个view,然后把三个部分和删除线分别画出来就可以了。

PriceView.java:

public class PriceView extends View{

	private String value = null;

	private int moneySize = -1;
	private int intSize = -1;
	private int decimalSize = -1;

	private String money = "¥";
	private String decimalPart = "";
	private String intPart = "";

	private int moneyStart = 0;
	private int intStart = 0;
	private int decimalStart = 0;

	private int textColor = 0;
	private boolean strike = false;
	private boolean withEndZero = true;

	private Paint mPaint;
	private Rect mTextBound = new Rect();
	private int totalWidth = 0;
	private int maxHeight = 0;

	public PriceView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		init(context, attrs);
	}

	public PriceView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public PriceView(Context context) {
		this(context, null);
	}

	private void init(Context context, AttributeSet attrs){
		mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		getProperties(context, attrs);
		calcTextDimens();
	}

	private void calcTextDimens() {

		totalWidth = 0;
		maxHeight = 0;

		//把text分成三个部分
		if(value == null || value.length() <= 0){
			return;
		}
		String arr[] = value.split("\\.");

		intPart = arr[0];
		if(intPart.length() > 0 && intPart.charAt(0) == '¥'){
			intPart = intPart.substring(1);
		}

		decimalPart = arr.length > 1? arr[1]:"";
        if(decimalPart != null){
        	if(!withEndZero){
        		decimalPart = decimalPart.replaceAll("0{1,}$", "");
        	}
            if(decimalPart != null && decimalPart.length() > 0){
                decimalPart = "."+decimalPart;
            }
        }

		//处理¥
		int moneyWidth = process(money, moneySize);
		moneyStart = getPaddingLeft();

		//处理整数部分
		int intWidth  = process(intPart, intSize);
		intStart = moneyStart + moneyWidth;

		//处理小数部分
		process(decimalPart, decimalSize);
		decimalStart = intStart + intWidth;

		totalWidth += getPaddingLeft() + getPaddingRight();
		maxHeight += getPaddingTop() + getPaddingBottom();

	}

	private int process(String text, int textSize){
		if(text == null || text.length() <= 0){
			return 0;
		}
		mPaint.setTextSize(textSize);
		int textWidth = (int) mPaint.measureText(text);
		mPaint.getTextBounds(text, 0, text.length(), mTextBound);
		totalWidth += textWidth;
		maxHeight = mTextBound.height() > maxHeight? mTextBound.height() : maxHeight;
		return textWidth;
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
	{
		int width = measureWidth(widthMeasureSpec);
		int height = measureHeight(heightMeasureSpec);
		setMeasuredDimension(width, height);
	}

	protected void onDraw(Canvas canvas)
	{
		super.onDraw(canvas);
		mPaint.setColor(textColor);
		//画中间的删除线
		if(strike){
			//mPaint.setFlags(Paint.STRIKE_THRU_TEXT_FLAG);是不可以的,为什么不可以可以自己试一下
			float startX = getPaddingLeft();
			float startY = (getMeasuredHeight() - getPaddingBottom() - getPaddingTop()) /2 + getPaddingTop();
			float stopX = getMeasuredWidth() - getPaddingRight();
			float stopY = startY;
			canvas.drawLine(startX, startY , stopX, stopY, mPaint);
		}
		//画¥
		mPaint.setTextSize(moneySize);
		canvas.drawText(money, moneyStart, getMeasuredHeight() - getPaddingBottom(), mPaint);
		//画整数部分
		mPaint.setTextSize(intSize);
		canvas.drawText(intPart, intStart, getMeasuredHeight() - getPaddingBottom(), mPaint);
		//画小数部分
		mPaint.setTextSize(decimalSize);
		canvas.drawText(decimalPart, decimalStart, getMeasuredHeight() - getPaddingBottom(), mPaint);
	}

	private int measureWidth(int measureSpec)
	{
		int mode = MeasureSpec.getMode(measureSpec);
		int val = MeasureSpec.getSize(measureSpec);
		int result = 0;
		switch (mode){
			case MeasureSpec.EXACTLY:
				result = val;
				break;
			case MeasureSpec.AT_MOST:
			case MeasureSpec.UNSPECIFIED:
				result = totalWidth;
				break;
		}
		return result;
	}

	private int measureHeight(int measureSpec)
	{
		int mode = MeasureSpec.getMode(measureSpec);
		int val = MeasureSpec.getSize(measureSpec);
		int result = 0;
		switch (mode){
			case MeasureSpec.EXACTLY:
				result = val;
				break;
			case MeasureSpec.AT_MOST:
			case MeasureSpec.UNSPECIFIED:
				result = maxHeight;
				break;
		}
		return result;
	}

	private void getProperties(Context context, AttributeSet attrs){
        //自定义的属性
		TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CartPriceValue);
        int textSize = a.getDimensionPixelSize(R.styleable.CartPriceValue_textSize, 14);
		String value = a.getString(R.styleable.CartPriceValue_value);
		int textColor = a.getColor(R.styleable.CartPriceValue_textColor, 0xffffff);
		int moneySize = a.getDimensionPixelSize(R.styleable.CartPriceValue_moneySize, textSize);
		int intSize = a.getDimensionPixelSize(R.styleable.CartPriceValue_intSize, textSize);
		int decimalSize = a.getDimensionPixelSize(R.styleable.CartPriceValue_decimalSize, textSize);
		boolean strike = a.getBoolean(R.styleable.CartPriceValue_strike, false);
		boolean withEndZero = a.getBoolean(R.styleable.CartPriceValue_withEndZero, true);
		this.value = value;
		this.textColor = textColor;
		this.moneySize = moneySize;
		this.intSize = intSize;
		this.decimalSize = decimalSize;
		this.strike = strike;
		this.withEndZero = withEndZero;
		a.recycle();
	}

	public void setText(String text){
		this.value = text;
		calcTextDimens();
	}
}

attr.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>

     <declare-styleable name="CartPriceValue">
        <attr name="value" format="reference|string" />
        <attr name="textColor" format="reference|color" />
        <attr name="textSize" format="reference|dimension" />
        <attr name="moneySize" format="reference|dimension" />
        <attr name="intSize" format="reference|dimension" />
        <attr name="decimalSize" format="reference|dimension" />
        <attr name="strike" format="boolean" />
        <attr name="withEndZero" format="boolean" />
    </declare-styleable>

</resources>

布局文件main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:cart="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:orientation="vertical" >

    <com.example.priceview.PriceView
        android:id="@+id/priceview1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        cart:value="¥12.345"
        cart:moneySize="14dp"
        cart:intSize="20dp"
        cart:decimalSize="16dp"
        cart:textColor="#ff0000"
        cart:strike="true"
        android:padding="10dp"/>

    <com.example.priceview.PriceView
        android:id="@+id/priceview2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        cart:value="¥12.0"
        cart:moneySize="14dp"
        cart:intSize="20dp"
        cart:decimalSize="16dp"
        cart:textColor="#ff0000"
        cart:strike="true"
        android:padding="10dp"/>

    <com.example.priceview.PriceView
        android:id="@+id/priceview3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        cart:value="¥12.0"
        cart:moneySize="14dp"
        cart:intSize="20dp"
        cart:decimalSize="16dp"
        cart:textColor="#ff0000"
        cart:strike="true"
        cart:withEndZero="false"/>

</LinearLayout>

工程源码下载:http://download.csdn.net/download/goldenfish1919/8512713

时间: 2024-12-15 01:59:08

Android-自定义显示价格的PriceView的相关文章

Android 自定义Adapter 但listview 只显示第一条数据

楼主让这个问题郁闷了一晚上.....在logcat里明明显示adapter的getview方法里的list大于一条数据 ,但posotion却一直是0.....运行后也只显示list[0]里面的数据....最后的最后原来错误出在布局文件上 我以前的是这样的; <ScrollView android:layout_width="fill_parent" android:layout_height="wrap_content" > <!-- listv

Android 自定义 ListView 显示网络歌曲列表

本文内容 环境 项目结构 演示自定义 ListView 显示网络歌曲列表 参考资料 本文最开始看的一个国人的文章,没有源代码,根据文中提供的源代码,自己新建的项目(最可气的是,没有图标图片资源,只能自己乱编),但程序不是很稳定,有时能显示出列表中的缩略图,有时显示不出来,还在主线程访问了网络.后看文章评论,作者给出英文原文链接,本来想这下没事了吧,结果下载源代码运行后,还是有问题~仔细看英文原文,原来他也是根据 Github 上一个项目的基础上搞的,只是添加了式样,以及显示完整的歌曲列表,包括歌

Android 自定义圆圈进度并显示百分比例控件(纯代码实现)

首先,感谢公司能给我闲暇的时间,来稳固我的技术,让我不断的去探索研究,在此不胜感激. 先不说实现功能,上图看看效果 这个是续上一次水平变色进度条的有一个全新的控件,理论实现原理 1.分析控件:该控件基本上是圆圈内嵌圆圈: 2.进度计算:其实是小学二年级数学题:当前进度/总数=百分比: 3.中间时间:呵呵,纯粹忽悠,不解释(当前时间). 理论总是和实践差距的太远,不扯淡,不吹嘘,贴代码: package com.spring.progressview; import java.text.Simpl

Android自定义Toast的时长、位置、及显示的View

Android自定义Toast 首先是自定义时长: 说是这么说,但是android自带的两个时长 LENGTH_SHORT (2秒) 和LENGTH_LONG (3.5秒)基本已经够用了,一般也没有特地去设置几十秒的Toast吧,这样的话,还不如直接弄一个Dialog来的直接. 我们先看看如何让Toast在3.5秒内自定义显示长度: public static void showShort(Context context, String msg, int duration) { final To

Android 自定义Gallery浏览图片

之前写的<Android ImageSwitcher和Gallery的使用>一文中提到我在教室一下午为实现那个效果找各种资料.期间在网上找了一个个人觉得比较不错的效果,现在贴图上来: 其实这个效果使用的知识点就是图像的获取.创建.缩放.旋转.Matrix类.Canvas类等,另外就是自定义的Gallery控件. 相信大家都期待马上上代码了吧,嘻嘻.(注释比较多,相信大家都能看懂.) main.xml: <?xml version="1.0" encoding=&quo

Android 自定义RecyclerView 实现真正的Gallery效果

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38173061 ,本文出自:[张鸿洋的博客] 上一篇博客我使用自定义HorizontalScrollView写了一个具有HorizontalScrollView效果和ViewPager特性的横向图片轮播,详见:Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果.其实制作横向滚动的不得不说另一个控件,就是Google

Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38140505 自从Gallery被谷歌废弃以后,Google推荐使用ViewPager和HorizontalScrollView来实现Gallery的效果.的确HorizontalScrollView可以实现Gallery的效果,但是HorizontalScrollView存在一个很大的问题,如果你仅是用来展示少量的图片,应该是没问题的,但是如果我希望HorizontalScr

Android 自定义View视图

创建全新的视图将满足我们独特的UI需求. 本文介绍在指南针开发中会用到的罗盘的界面UI,通过继承View类实现的自定义视图,以此来深刻了解自定义视图. 实现效果图: 源代码: 布局文件activity_main(其中CompassView继承View类): <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.

Android自定义View之LoadingLayout

介绍 上一篇博文写了一个通用的加载view,这篇在加载view的基础在包裹一层就是LoadingLayout了,主要的目的是免去每次加载时要隐藏主内容布局,然后加载成功之后显示主内容布局这些繁琐操作.如果你还不了解loadingView,可以简单的看一下上一篇博文:Android 自定义通用的loadingview,实现原理很简单,就是LoadingLayout在包裹内容层的基础上,在代码里添加loadingView作为第二个子view,所以不做过多讲解,大家看完直接下载源码参考. Loadin