转载请标明出处: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;
private boolean hasComma = false; 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);
} public void setText(String text){
this.value = text;
calcTextDimens();
} 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);
}
if(intPart.indexOf(",") >= 0){
hasComma = true;
}else{
hasComma = false;
}
//小数部分
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);
}
int y = getMeasuredHeight() - getPaddingBottom();
if(hasComma){
y -= dp2px(getContext(), 3);
}
//画¥
mPaint.setTextSize(moneySize);
canvas.drawText(money, moneyStart, y, mPaint);
//画整数部分
mPaint.setTextSize(intSize);
canvas.drawText(intPart, intStart, y, mPaint);
//画小数部分
mPaint.setTextSize(decimalSize);
canvas.drawText(decimalPart, decimalStart, y, 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 static int px2dp(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
public static int dp2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}

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>

project源代码下载:http://download.csdn.net/download/goldenfish1919/8512713

ps:

(1)在一个ListView中使用这个PriceView的时候,发现有的时候价格被截断没有展示出来,后来才发现是由于Listview中的View复用导致的。

因此须要在setText()中显式的调用一下requestLayout()。它会导致又一次调用onMeasure()。

(2)后来又发现个问题,当整数部分带有逗号的时候,逗号会显示不全,不知道是哪块代码出的问题。有大神不吝赐教下吗?

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

  1. Android自己定义DataTimePicker(日期选择器)

    Android自己定义DataTimePicker(日期选择器)  笔者有一段时间没有发表关于Android的文章了,关于Android自己定义组件笔者有好几篇想跟大家分享的,后期会记录在博客中.本篇 ...

  2. Android UI--自定义ListView(实现下拉刷新+加载更多)

    Android UI--自定义ListView(实现下拉刷新+加载更多) 关于实现ListView下拉刷新和加载更多的实现,我想网上一搜就一堆.不过我就没发现比较实用的,要不就是实现起来太复杂,要不就 ...

  3. ANDROID自己定义视图——onLayout源代码 流程 思路具体解释

    转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 简单介绍: 在自己定义view的时候.事实上非常easy.仅仅须要知道3步骤: 1.測量- ...

  4. Android 自己定义View (二) 进阶

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24300125 继续自己定义View之旅.前面已经介绍过一个自己定义View的基础 ...

  5. Android 自己定义ScrollView ListView 体验各种纵向滑动的需求

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38950509.本文出自[张鸿洋的博客] 1.概述 群里的一个哥们有个需求是这种: ...

  6. Android自己定义控件系列五:自己定义绚丽水波纹效果

    尊重原创!转载请注明出处:http://blog.csdn.net/cyp331203/article/details/41114551 今天我们来利用Android自己定义控件实现一个比較有趣的效果 ...

  7. Android动态控制状态栏显示和隐藏

    记得之前有朋友在留言里让我写一篇关于沉浸式状态栏的文章,正巧我确实有这个打算,那么本篇就给大家带来一次沉浸式状态栏的微技巧讲解. 其实说到沉浸式状态栏这个名字我也是感到很无奈,真不知道这种叫法是谁先发 ...

  8. Android自己定义控件:进度条的四种实现方式

    前三种实现方式代码出自: http://stormzhang.com/openandroid/2013/11/15/android-custom-loading/ (源代码下载)http://down ...

  9. android 自己定义控件

    Android自己定义View实现非常easy 继承View,重写构造函数.onDraw.(onMeasure)等函数. 假设自己定义的View须要有自己定义的属性.须要在values下建立attrs ...

随机推荐

  1. QT进度条QProgressBar的练习

    progressbar.h #ifndef PROGRESSBAR_H #define PROGRESSBAR_H #include <QProgressBar> class QStrin ...

  2. Unix/Linux环境C编程入门教程(5) Red Hat Enterprise Linux(RHEL)环境搭建

    Unix/Linux版本众多,我们推荐Unix/Linux初学者选用几款典型的Unix/Linux操作系统进行学习. 通过./a.out ./Y.out执行出结果,证明C++程序编译成功,也就说明li ...

  3. 剑指offer 25 二叉树中和为某一值的路径

    非递归方法: class Solution { public: vector<vector<int>> FindPath(TreeNode* root,int expectNu ...

  4. frameset常用属性

    框架是网页画面分成几个框窗(不同的窗口对应不同页面以几个网页的形式显示),同时取得多个 src的地址.页面所有框架标记需要放在一个总起的 html 档,这个档案只记录了该框架如何分割 ,不会显示任何资 ...

  5. lucene3.6笔记添加搜索功能

    lucene为程序添加搜索功能,此功能基于已创建好的文档的索引之上.这里我已经为一些文档建立了索引,并保存到硬盘上.下面开始针对这些索引,添加搜索功能. 1.简单的TermQuery搜索 Java代码 ...

  6. Sicily 4495. Print permutations

    http://soj.me/4495 按字典序生成字符串的全排列 直接递归: #include <iostream> #include <string> #include &l ...

  7. wget多进程抓取的实现

    把以前博客的东西夜迁移过来吧,这个是以前公司做的,原来放在csdn里面,先切过来. 用多进程实现的 wget多进程抓取的实现,有问题联系我 (微博:偶是周亮) #!/bin/bash url_path ...

  8. ASPxGridView-单元格合并

    <dx:ASPxGridView ID="gridView" runat="server" ClientInstanceName="gvResu ...

  9. 在WHERE子句中引用取别名的列

    版权说明:作者:张颖希(PocketZ's Blog)出处:http://www.cnblogs.com/PocketZ本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页 ...

  10. Android自定义View和控件之一-定制属于自己的UI

    照例,拿来主义.我的学习是基于下面的三篇blog.前两是基本的流程,第三篇里有比较细致的绘制相关的属性.第4篇介绍了如何减少布局层次来提高效率. 1. 教你搞定Android自定义View 2. 教你 ...