美文网首页Android项目实战Android开发Android知识
MPAndroidChart项目实战(七)——自定义横向柱状图

MPAndroidChart项目实战(七)——自定义横向柱状图

作者: 天一方蓝 | 来源:发表于2017-10-26 15:54 被阅读220次
    1016.png
    本文出自:http://blog.csdn.net/dt235201314/article/details/77248347
    一丶效果演示

    二丶需求分析技术点
    1.产品要求,显示每个品类的占比,形成对比
    2.MPAndroidChart可行性分析,可行,运用横向柱状图,设置最大值为100%,坐等设计图
    3.MPAndroidChart实战问题分析
    1).当品类多平分100%时,柱状图太少不好看,处理方式,最大值为百分比最大值,问题解决
    2 ).品类名称长短不一时,对齐方式,无法解决,不得不弃疗
    4.自定义分析,组合图,每行为单位,一个统一xml布局,最大值占满一行,动画
    5.技术点分析
    LinearLayout.LayoutParams完成宽度测量
    ObjectAnimator完成动画效果
    基础链接推荐:http://blog.csdn.net/harvic880925/article/details/50598322
    ViewTreeObserver.OnPreDrawListener()测量绘制宽高
    基础链接推荐:http://www.jianshu.com/p/5b026ffc36f1

    ViewTreeObserver祥解:http://blog.csdn.net/hardworkingant/article/details/77408329
    三丶核心代码
    1.造数据,实体类

    /**
     * <pre>
     *     author : JinBiao
     *     CSDN : http://my.csdn.net/DT235201314
     *     time   : 2017/08/16
     *     desc   : 用于横向柱状图数据
     *     version: 1.0
     * </pre>
     */
    
    public class BarDataEntity implements Serializable{
        private List<Type> typeList;
    
        public List<Type> getTypeList() {
            return typeList;
        }
        
        public static class Type implements Serializable {
            private String typeName;//类型名称
            private int sale;//销量
            private double typeScale;//类型占比
    
            public String getTypeName() {
                return typeName;
            }
    
            public void setTypeName(String typeName) {
                this.typeName = typeName;
            }
    
            public int getSale() {
                return sale;
            }
    
            public void setSale(int sale) {
                this.sale = sale;
            }
    
            public double getTypeScale() {
                return typeScale;
            }
    
            public void setTypeScale(double typeScale) {
                this.typeScale = typeScale;
            }
        }
    
        public List<Type> parseData(){
            typeList = new ArrayList<>();
            Random r = new Random();
            int all=0;
            for (int i= 0;i<=6;i++){
                Type type = new Type();
                type.setSale(r.nextInt(100));
                type.setTypeName("品类" + i);
                typeList.add(type);
            }
            for (int i= 0;i<=6;i++){
                all+= typeList.get(i).getSale();
            }
            for (int i= 0;i<=6;i++){
                double typeScale = (double) typeList.get(i).getSale()/all;
                typeList.get(i).setTypeScale(typeScale);
                System.out.println("==>"+typeList.get(i).getTypeScale());
            }
            return typeList;
        }
    }
    

    2.行布局xml,参考设计图

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:paddingBottom="8dp"
        android:paddingLeft="12dp"
        android:paddingRight="10dp"
        android:paddingTop="8dp">
    
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:orientation="horizontal"
            android:paddingRight="10dp">
    
            <TextView
                android:id="@+id/index"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="0" />
    
            <TextView
                android:id="@+id/name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="right"
                android:text="产品质量" />
        </LinearLayout>
    
        <LinearLayout
            android:id="@+id/bar_container"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="3"
            android:orientation="horizontal"
            android:gravity="left|center_vertical">
    
            <TextView
                android:id="@+id/bar"
                android:layout_width="wrap_content"
                android:layout_height="20dp"
                android:background="#0CD3F4"
                />
    
            <TextView
                android:id="@+id/percent"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:paddingLeft="10dp"
                android:text="0%"
                android:textColor="#0CD3F4" />
        </LinearLayout>
    
    </LinearLayout>
    

    3.核心方法
    赋值 动画 测量

    public void bindData() {
        container = (LinearLayout) itemView.findViewById(R.id.container);
        container.removeAllViews();
        BarDataEntity data = new BarDataEntity();
        data.parseData();
        if (data == null || data.getTypeList() == null) {
            return;
        }
        int color = Color.parseColor("#3FA0FF");
        double maxScale = 0;
        for (int i = 0; i < data.getTypeList().size(); i++) {
            if (data.getTypeList().get(i).getTypeScale() > maxScale)
                maxScale = data.getTypeList().get(i).getTypeScale();
        }
        for (int i = 0; i < data.getTypeList().size(); i++) {
            final View item = LayoutInflater.from(itemView.getContext()).inflate(R.layout.h_bar_item, container, false);
            final BarDataEntity.Type type = data.getTypeList().get(i);
            ((TextView) item.findViewById(R.id.index)).setText("");
            ((TextView) item.findViewById(R.id.name)).setText(type.getTypeName());
            ((TextView) item.findViewById(R.id.index)).setText("" + i);
            final View bar = item.findViewById(R.id.bar);
            bar.setBackgroundColor(color);
            ((TextView) item.findViewById(R.id.percent)).setText(format.format(type.getTypeScale() * 100) + "%");
            ((TextView) item.findViewById(R.id.percent)).setTextColor(color);
            final double finalMaxScale = maxScale;
            item.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                @Override
                public boolean onPreDraw() {
                    item.getViewTreeObserver().removeOnPreDrawListener(this);
                    int barContainerWidth = item.findViewById(R.id.bar_container).getWidth();
                    int percentTxtWidth = item.findViewById(R.id.percent).getWidth();
                    final int initWidth = barContainerWidth - percentTxtWidth;
                    final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) bar.getLayoutParams();
                    lp.width = (int) (initWidth * type.getTypeScale()/ finalMaxScale * 100 / 100);
                    bar.setLayoutParams(lp);
                    item.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            final int initWidth = bar.getWidth();
                            final ObjectAnimator anim = ObjectAnimator.ofFloat(bar, "alpha", 0.0F, 1.0F).setDuration(1500);
                            anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                                @Override
                                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                                    float cVal = (Float) anim.getAnimatedValue();
                                    lp.width = (int) (initWidth * cVal);
                                    bar.setLayoutParams(lp);
                                }
                            });
                            anim.start();
                        }
                    }, 0);
                    return false;
                }
            });
            container.addView(item);
        }
    }
    

    四丶总结
    1.MPAndroidChart虽然强大并不能解决所有问题,自定义才是王道
    2.关于Java代码实现xml布局添加要多加学习,动画,简单实用的动画必须掌握。
    3.关于View还有很多陌生的方法没有学习接触到,在自定义系列中逐渐掌握学习
    五丶往期相关文章推荐
    MPAndroidChart常见设置属性(一)——应用层
    MPAndroidChart项目实战(一)——实现对比性柱状图
    MPAndroidChart项目实战(二)——双平滑曲线(双折线图)和MarkView实现
    MPAndroidChart项目实战(三)——饼状图实现和文字重合问题解决
    MPAndroidChart项目实战(四)——柱状图实现及X轴文字不显示问题和柱状图上显示文字
    MPAndroidChart X轴文字斜着显示
    MPAndroidChart项目实战(五)——组合图实现趋势图
    MPAndroidChart项目实战(六)——自定义1MPAndroidChart滑动冲突解决(搞不定产品设计师就只能搞自己)
    MPAndroidChart项目实战(七)——自定义横向柱状图
    MPAndroidChart项目实战(八)——自定义分段堆积柱状图
    MPAndroidChart项目实战(九)——自定义带文字分段堆积柱状图
    六丶跪求关注下载源码,200粉小目标
    欢迎关注我的博客及微信公众号,后面会给大家带来更多相关MPAndroidChart无法解决的仿MPAndroidChart图标自定义控件
    源码下载记得顺便Star哦~
    下载链接:https://github.com/JinBoy23520/MPAndroidChartDemoByJin

    写在最后微信扫码提问

    image

    相关文章

      网友评论

        本文标题:MPAndroidChart项目实战(七)——自定义横向柱状图

        本文链接:https://www.haomeiwen.com/subject/haskpxtx.html