android开发自定义View实现柱状图

 更新时间:2016年10月2日 16:23  点击:1481
下面我们来看一篇关于android开发自定义View实现柱状图的例子,希望这篇文章能够对各位带来帮助,具体的细节步骤如下文介绍。

为了使文章中的代码看起来简洁一点,便于理解一点,我就不把Paint的实例化代码贴出来了,另外提示:本文所有变量都是我定死的,各位可以根据需求来自己设置getset方法.

device-2016-08-19-163253

参数:

private Paint mPaint;//画文字和XY轴的画笔
private Paint mPaintColumn;//画圆柱的画笔
private final float START_X = 200;//Y轴左上角X坐标
private final float START_Y = 200;//Y轴左上角Y坐标
private boolean canLoad = true;//是否开始画图
private float XSpace = 150;//Y轴每个数字间距
private float XWidth = 900;//X轴总长度
private String[] XNames = {"测试1", "测试2", "测试3", "测试4", "测试5"};
private int YCount = 10;//Y轴数值的个数(包括0)
private float YSpace = 100;//Y轴每个数字间距
private float YHeight = 1000;//Y轴总长度
private float ColumsWidth = 50;//长方形宽(圆柱)

YHeight = (float) (YHeight + getTxtHeight(mPaint));//这个代码的意思是:将Y轴的值和文字高度加起来,因为文字有高度,如果
不算文字高度,最后一个Y轴的值就会比计划高一点

//获取文字的高
public double getTxtHeight(Paint mPaint) {
 Paint.FontMetrics fm = mPaint.getFontMetrics();
 return Math.ceil(fm.descent - fm.ascent);
}

关键代码draw:

@Override
public void draw(Canvas canvas) {
    super.draw(canvas);
    if (canLoad) {
        canvas.drawLine(START_X, START_Y, START_X, YHeight + START_Y, mPaint);//Y轴
        canvas.drawLine(START_X, YHeight + START_Y, START_X + XWidth, YHeight + START_Y, mPaint);//X轴
        float MaxTextWidth = mPaint.measureText("1000");//这里我知道最长的字为1000,所以这么写,根据不同情况改
        float TxtHeight = (float) getTxtHeight(mPaint);//mPaint所画文字的高度
        //Y轴上的数值
        for (int i = 0; i <= YCount; i++) {
            String count = 100 * i + "";
            canvas.drawText(count, START_X - MaxTextWidth, YHeight + START_Y - YSpace * i, mPaint);
        }
        //X轴上的数值
        for (int i = 0; i < XNames.length; i++) {
            String name = XNames[i];
            canvas.drawText(name, START_X + XSpace * (i + 1), YHeight + START_Y + TxtHeight, mPaint);
        }
 
        //圆柱和圆柱上面的具体数值
        for (int i = 0; i < XNames.length; i++) {
            String count = (i + 1) * 100 + "";
            canvas.drawRect(START_X + XSpace * (i + 1) - ColumsWidth / 2, START_Y + YHeight - (i + 1) * YSpace, START_X + XSpace * (i + 1) + ColumsWidth / 2, YHeight + START_Y, mPaintColumn);
            canvas.drawText(count, ColumsWidth/2+START_X + XSpace * (i + 1) - ColumsWidth / 2, START_Y + YHeight - (i + 1) * YSpace-10, mPaint);
        }
 
    }
}

下面我们来看一篇关于android自定义View之获取文字高度例子,希望这篇文章能够对各位带来帮助。

自定义View经常会画文字,那么就可能需要获取文字的高度,这里介绍一种好用的方法:


public double getTxtHeight(Paint mPaint) {
    Paint.FontMetrics fm = mPaint.getFontMetrics();
    return Math.ceil(fm.descent - fm.ascent);
}

参数为Paint,就是你画文字的画笔,效果如下

device-2016-08-19-150638

canvas.drawText("测试文字", 300, 300, mPaint);
canvas.drawText("文字的高度为:" + getTxtHeight(mPaint) + "px", 300, 400, mPaint);

下面我们来看一篇关于android开妇这自定义View之使用TextPaint使\n等符号生效的例子,这个是换行符号了,希望此文章对各位有帮助。

同学们现在或以后自定义View画文字的时候,肯定会需要将文字换行,大家都知道\n,那么我们来画试一下:

canvas.drawText("这里是测试换行符\n第二行",300,300,mPaint);

device-2016-08-19-165510

如何解决呢?使用TextPaint:

private TextPaint mPaint;

实例化方式与Paint一致(本来就是Paint的儿子)

接下来:

StaticLayout layout = new StaticLayout("这里是测试换行符\n第二行", mPaint,
(int) mPaint.measureText("这里是测试换行符\n第二行"), Layout.Alignment.ALIGN_NORMAL, 1.0F, 0.0F, true);
canvas.translate(300,300);
layout.draw(canvas);

效果:


device-2016-08-19-165858

 

本文章来为各位介绍一篇关于Android设置WebView的放大倍数例子,希望这篇文章能够帮助到各位朋友,有兴趣的朋友可以进来看看吧。

在APP开发的过程中,不免会遇到加载WebView的情况,一般我们都会固定WebView不能左右滑动但可以上下滑动,有时候界面加载出来之后他的格式跟原网页一模一样,那么就会带来一个问题:整体缩小。真实近视眼的悲哀啊,那么我们就需要放大倍数,但是不能左右滑动,这时候格式就会被灵活的打乱,不影响网页的阅读,这个神奇的属性就是:

webView.setInitialScale(220);

里面的参数是可以自己设置的,你可以根据计算不同手机屏幕的宽度和高度来设置不同的倍数,那么显示效果就会更加兼容了

自定义布局的日历这个在一些注册网站用到的比较多了,下面我们来看一段小编整理的Android 自定义布局的日历代码,希望下面的内容对各位有用。


系统自带的日历虽然好用,但是不符合某些项目的需求,所以需要自定义布局,看网上许多自定义View完成自定义日历的,

自认水平不够,无法驾驭,所以采用gridview来实现。


效果

CalendarUtils:(获取当前年月对应的数据数组)


package kyle.com.zujian;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
 
/**
 * Created by kyle on 2016/8/12 0012.
 * 获取某年某月的日期,界面上第一天为周日
 * 通过传的年和月,获取对应年月的日期和第一天是周几
 */
public class CalendarUtils {
    private static int FIRST_DAY_OF_WEEK;//第一天
    private static Calendar calendar;//日历
 
 
    public static List<DateEntity> getDate(int year, int month) {
        if (year <= 0 || month < 1 || month > 12) {
            return new ArrayList<>();//当年和月不符合规则时,返回空list
        }
        List<DateEntity> dates = new ArrayList<>();
        calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);//设置年
        calendar.set(Calendar.MONTH, month - 1);//设置月
        calendar.set(Calendar.DAY_OF_MONTH, 1);//设置第一天
        FIRST_DAY_OF_WEEK = calendar.get(Calendar.DAY_OF_WEEK) - 1;//获得第一天是周几 0:周日 6周六
        for (int i = 0; i < FIRST_DAY_OF_WEEK; i++) {//假设是周日则跳过,假设不是周日,就添加对应数目的空白item
            DateEntity entity = new DateEntity();
            dates.add(entity);
        }
        int count = checkDays(year, month);//获取当前年月的天数
        for (int i = 0; i < count; i++) {
            DateEntity entity2 = new DateEntity(year, month, i + 1);
            dates.add(entity2);
        }
        return dates;
    }
 
    /***
     * 判断当前年月有多少天
     *
     * @param year
     * @param month
     * @return
     */
    private static int checkDays(int year, int month) {
        if (year < 1 || month > 12 || month < 1) {
            return 0;
        }
        switch (month) {
            case 2:
                if (year % 4 == 0) {
                    return 29;
                } else {
                    return 28;
                }
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                return 31;
            case 4:
            case 6:
            case 9:
            case 11:
                return 30;
        }
        return 0;
    }
}

实体类:DateEntity

package kyle.com.zujian;
 
/**
 * Created by Administrator on 2016/8/9 0009.
 */
public class DateEntity {
    private int year;
    private int month;
    private int day;
 
    @Override
    public String toString() {
        return "DateEntity{" +
                "year=" + year +
                ", month=" + month +
                ", day=" + day +
                '}';
    }
 
    public DateEntity(){
 
}
    public DateEntity( int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }
 
 
    public int getYear() {
        return year;
    }
 
    public void setYear(int year) {
        this.year = year;
    }
 
    public int getMonth() {
        return month;
    }
 
    public void setMonth(int month) {
        this.month = month;
    }
 
    public int getDay() {
        return day;
    }
 
    public void setDay(int day) {
        this.day = day;
    }
}

CalendarGridView:(自定义的gridview,把代码转移到这里面,方便调用.)

package kyle.com.zujian;
 
import android.content.Context;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
 
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
 
/**
 * Created by kyle on 2016/8/15 0015.
 * 自定义日历gridview
 */
public class CalendarGridView extends GridView {
 
    private Context mContext;
    private List<DateEntity> mList = new ArrayList<>();
    private MyAdapter mAdapter;
    private Calendar calendar;
    /***
     * 今天
     */
    private int NOW_YEAR;//当前年
    private int NOW_MONTH;//当前月
    private int NOW_DAY;//当前日
 
    public CalendarGridView(Context context) {
        super(context, null);
        mContext = context;
    }
 
    public CalendarGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        calendar = Calendar.getInstance();//获取日历实例
        NOW_YEAR = calendar.get(Calendar.YEAR);//当前年
        NOW_MONTH = calendar.get(Calendar.MONTH) + 1;//当前月
        NOW_DAY = calendar.get(Calendar.DAY_OF_MONTH);//当前日
        mAdapter = new MyAdapter();//实例化和设置适配器
        setAdapter(mAdapter);
    }
 
    public void init(int year, int month) {
        if (year < 1 || month < 1 || month > 12) {
            Toast.makeText(mContext, "年份或月份错误!", Toast.LENGTH_SHORT).show();
            return;
        }
        mList.clear();
        for (DateEntity entity : CalendarUtils.getDate(year, month)) {
            mList.add(entity);
        }
        mAdapter.notifyDataSetChanged();
    }
 
    private class MyAdapter extends BaseAdapter {
 
        @Override
        public int getCount() {
            return mList.size();
        }
 
        @Override
        public Object getItem(int position) {
            return mList.get(position);
        }
 
        @Override
        public long getItemId(int position) {
            return position;
        }
 
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            MyHolder holder;
            if (convertView == null) {
                convertView = View.inflate(mContext, R.layout.item_grid, null);
                holder = new MyHolder();
                holder.llMain = (LinearLayout) convertView.findViewById(R.id.ll_main);
                holder.tvDate = (TextView) convertView.findViewById(R.id.tv_date);
                holder.tvCount = (TextView) convertView.findViewById(R.id.tv_count);
                convertView.setTag(holder);
            } else {
                holder = (MyHolder) convertView.getTag();
            }
            int year = mList.get(position).getYear();
            int month = mList.get(position).getMonth();
            int day = mList.get(position).getDay();
            if (year == NOW_YEAR && month == NOW_MONTH && day == NOW_DAY) {
                holder.llMain.setBackgroundResource(R.color.red);
                holder.tvDate.setTextColor(ContextCompat.getColor(mContext, R.color.white));
                holder.tvCount.setTextColor(ContextCompat.getColor(mContext, R.color.white));
            } else {
                holder.llMain.setBackgroundResource(R.color.white);
                holder.tvDate.setTextColor(ContextCompat.getColor(mContext, R.color.black));
                holder.tvCount.setTextColor(ContextCompat.getColor(mContext, R.color.black));
            }
            if (day != 0) {
                holder.tvDate.setText(mList.get(position).getDay() + "");
            } else {
                holder.tvDate.setText("");
            }
            return convertView;
        }
    }
 
    private class MyHolder {
        private LinearLayout llMain;
        private TextView tvDate;
        private TextView tvCount;
    }
}

在Activity里面这样调用:

CalendarGridView mGv= (CalendarGridView) findViewById(R.id.gv);
mGv.init(2016,8);
 

当然,布局和实体类都可以自己去根据需求写,而如果想要真正的日历功能,则可以使用viewpager+fragment实现了

[!--infotagslink--]

相关文章

  • Android子控件超出父控件的范围显示出来方法

    下面我们来看一篇关于Android子控件超出父控件的范围显示出来方法,希望这篇文章能够帮助到各位朋友,有碰到此问题的朋友可以进来看看哦。 <RelativeLayout xmlns:an...2016-10-02
  • C#创建自定义控件及添加自定义属性和事件使用实例详解

    这篇文章主要给大家介绍了关于C#创建自定义控件及添加自定义属性和事件使用的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用C#具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧...2020-06-25
  • JS实现自定义简单网页软键盘效果代码

    本文实例讲述了JS实现自定义简单网页软键盘效果。分享给大家供大家参考,具体如下:这是一款自定义的简单点的网页软键盘,没有使用任何控件,仅是为了练习JavaScript编写水平,安全性方面没有过多考虑,有顾虑的可以不用,目的是学...2015-11-08
  • Android开发中findViewById()函数用法与简化

    findViewById方法在android开发中是获取页面控件的值了,有没有发现我们一个页面控件多了会反复研究写findViewById呢,下面我们一起来看它的简化方法。 Android中Fin...2016-09-20
  • Android模拟器上模拟来电和短信配置

    如果我们的项目需要做来电及短信的功能,那么我们就得在Android模拟器开发这些功能,本来就来告诉我们如何在Android模拟器上模拟来电及来短信的功能。 在Android模拟...2016-09-20
  • 夜神android模拟器设置代理的方法

    夜神android模拟器如何设置代理呢?对于这个问题其实操作起来是非常的简单,下面小编来为各位详细介绍夜神android模拟器设置代理的方法,希望例子能够帮助到各位。 app...2016-09-20
  • android自定义动态设置Button样式【很常用】

    为了增强android应用的用户体验,我们可以在一些Button按钮上自定义动态的设置一些样式,比如交互时改变字体、颜色、背景图等。 今天来看一个通过重写Button来动态实...2016-09-20
  • Android WebView加载html5页面实例教程

    如果我们要在Android应用APP中加载html5页面,我们可以使用WebView,本文我们分享两个WebView加载html5页面实例应用。 实例一:WebView加载html5实现炫酷引导页面大多...2016-09-20
  • 深入理解Android中View和ViewGroup

    深入理解Android中View和ViewGroup从组成架构上看,似乎ViewGroup在View之上,View需要继承ViewGroup,但实际上不是这样的。View是基类,ViewGroup是它的子类。本教程我们深...2016-09-20
  • Android自定义WebView网络视频播放控件例子

    下面我们来看一篇关于Android自定义WebView网络视频播放控件开发例子,这个文章写得非常的不错下面给各位共享一下吧。 因为业务需要,以下代码均以Youtube网站在线视...2016-10-02
  • 自定义jquery模态窗口插件无法在顶层窗口显示问题

    自定义一个jquery模态窗口插件,将它集成到现有平台框架中时,它只能在mainFrame窗口中显示,无法在顶层窗口显示. 解决这个问题的办法: 通过以下代码就可能实现在顶层窗口弹窗 复制代码 代码如下: $(window.top.documen...2014-05-31
  • Android用MemoryFile文件类读写进行性能优化

    java开发的Android应用,性能一直是一个大问题,,或许是Java语言本身比较消耗内存。本文我们来谈谈Android 性能优化之MemoryFile文件读写。 Android匿名共享内存对外A...2016-09-20
  • Android设置TextView竖着显示实例

    TextView默认是横着显示了,今天我们一起来看看Android设置TextView竖着显示如何来实现吧,今天我们就一起来看看操作细节,具体的如下所示。 在开发Android程序的时候,...2016-10-02
  • 自定义feignClient的常见坑及解决

    这篇文章主要介绍了自定义feignClient的常见坑及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-10-20
  • pytorch 自定义卷积核进行卷积操作方式

    今天小编就为大家分享一篇pytorch 自定义卷积核进行卷积操作方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-05-06
  • android.os.BinderProxy cannot be cast to com解决办法

    本文章来给大家介绍关于android.os.BinderProxy cannot be cast to com解决办法,希望此文章对各位有帮助呀。 Android在绑定服务的时候出现java.lang.ClassCastExc...2016-09-20
  • Android 实现钉钉自动打卡功能

    这篇文章主要介绍了Android 实现钉钉自动打卡功能的步骤,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下...2021-03-15
  • Vue 组件复用多次自定义参数操作

    这篇文章主要介绍了Vue 组件复用多次自定义参数操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-27
  • Android 开发之布局细节对比:RTL模式

    下面我们来看一篇关于Android 开发之布局细节对比:RTL模式 ,希望这篇文章对各位同学会带来帮助,具体的细节如下介绍。 前言 讲真,好久没写博客了,2016都过了一半了,赶紧...2016-10-02
  • PHP YII框架开发小技巧之模型(models)中rules自定义验证规则

    YII的models中的rules部分是一些表单的验证规则,对于表单验证十分有用,在相应的视图(views)里面添加了表单,在表单被提交之前程序都会自动先来这里面的规则里验证,只有通过对其有效的限制规则后才能被提交,可以很有效地保证...2015-11-24