自定义圆环百分占比view (label文字支持自动换行 和设置显示行数)

按照国际惯例,先上效果图

1.png
2.png
3.png

数据结构

从图可以看出我们需要标志类型的label 数量value 所占的角度angle 还有代表的颜色,得出数据结构如下

public static class Entry implements Comparable {
        public String label;
        public int value;
        public float angle;
        public int color;

        public Entry(String label, int value) {
            this.label = label;
            this.value = value;
        }

        @Override
        public int compareTo(@NonNull Object o) {
            Entry e = (Entry) o;
            if (value > e.value)
                return -1;
            if (value < e.value)
                return 1;
            return 0;
        }
    }

需求分析

按照数据总数平分一个圆,但是可能存在不能整分的情况,还有可能分的角度太小都看不到。

  • 最小角度为2,小于2度的设置成2度,方便查看
  • 按照Entry 的value 值分配角度e.angle = (360.0f * e.value) / count + arrearage;(count总个数,arrearage为上一个亏欠的度数)
  • 上面亏欠的度数arrearage = e.angle - 2f (<0) ,由下一个项目补偿
  • 如果全部计算完毕之后arrearage < 0 ,既还有欠费,那么再循环一遍,重新分配一次
  • 为了简化程序,arrearage 亏欠补偿是由下一个补偿的,没有考虑平均分摊,而且只有补偿之后e.angle + arrearage > 2 角度仍然大于2度的才有资格替上面一个补偿亏欠

代码

注释已经写的很清楚了,这里就不再解释,具体的坐标计算了,里面包括了一些数学的东西,椭圆的知识忘了可以百度一下,还有解决了TextPaint 绘制文字重叠不自动换行的问题,具体参考 Canvas的drawText绘制文本自动换行(支持设置显示最大行数)

自定义view : PieChart.java

public class PieChart extends View {

    ArrayList<Entry> mDataSet = new ArrayList<>();
    Paint mPaint;
    //写小圆文字 自动换行和限制最大行数
    private TextPaint mTextPain;
    private static final int MAX_LINE = 2;

    public PieChart(Context context) {
        super(context);
        init();
    }

    public PieChart(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public PieChart(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public PieChart(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    /**
     *
     * @param data 由于CompanyInfo 限制,最多只有 6个数据项
     * @param centerText
     */
    public void setData(ArrayList<Entry> data, String centerText) {
        mDataSet.clear();
        if (data != null) {
            mDataSet.addAll(data);
        }
        mCenterText = centerText;
        preCalcute();
        this.requestLayout();
    }


    public void setData(String[] labels, int values[], String centerText) {
        mDataSet.clear();
        for (int i = 0; i < labels.length; i++) {
            mDataSet.add(new Entry(labels[i], values[i]));
        }
        mCenterText = centerText;
        preCalcute();
        this.requestLayout();
    }


    // 计算角度,颜色
    private void preCalcute() {
        //计算 颜色(最大->最小 按COLORS数字依次分配,所以先排序
        ArrayList<PieChart.Entry> tmp = new ArrayList<>(mDataSet.size());
        tmp.addAll(mDataSet);

        Collections.sort(tmp);

        int i = 0;
        for (Entry e : tmp) {
            e.color = COLORS[i++];
        }

        if (mSortData) {
            Collections.sort(mDataSet);
        }

        int count = 0;
        for (Entry e : mDataSet) {
            count += e.value;
        }

        mCount = count;
        //计算角度
        float arrearage = 0;//用于补偿的中间变量,初始化0
        for (Entry e : mDataSet) {
            e.angle = (360.0f * e.value) / count + arrearage;
            // 角度太小,就画不出来了,所以设置最小角度为2,把多占用的让下一个承担
            if (e.angle < 2f) {
                arrearage = e.angle - 2f;//这是欠的度数
                e.angle = 2;
            } else {
                arrearage = 0;
            }
        }
        if (arrearage < 0) {//最后还有欠费,就再循环一遍,让大家(下一个)分担下欠费
            for (Entry e : mDataSet) {
                if (e.angle + arrearage > 2) {//如果分担后仍然大于2,就让他分担
                    e.angle += arrearage;
                    break;
                }
            }
        }

        Locale locale = Locale.getDefault();
        if (tmp.size() < 6) {//下面的小圆小于6个
            singleItemWidth = convertDpToPixel(63);
        } else {
            singleItemWidth = convertDpToPixel(56);
        }

        if (locale.getLanguage().toLowerCase().startsWith("zh")) {
            textSizeLabel = convertDpToPixel(14);
        } else {
            if (tmp.size() < 6) {
                textSizeLabel = convertDpToPixel(13);
            } else {
                textSizeLabel = convertDpToPixel(11);
            }
        }
    }

    //是否需要对数据进行排序
    boolean mSortData;

    public void setSort(boolean sort) {
        mSortData = sort;
    }

    //预制颜色,从大到小
    final int COLORS[] = {0xFF00A7CF, 0xFF8E7BE6, 0xFF0179B1, 0xFF73AC1A, 0xFFF5B910, 0xFFA5BBD1,
            0xFF00A7CF, 0xFF8E7BE6, 0xFF0179B1, 0xFF73AC1A, 0xFFF5B910, 0xFFA5BBD1,};

    //中心的文字“总量”多语言由外面传入
    String mCenterText;
    //总量
    int mCount;

    private void init() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mTextPain = new TextPaint();
        mTextPain.setAntiAlias(true);
    }

    // 上下padding
    float padding = convertDpToPixel(12);
    // 大圆的半径
    float radius = convertDpToPixel(65);
    // 圆环的宽度
    float border = radius / 4;
    // 小圆半径
    float sradius = convertDpToPixel(15);

    //大圆心 数字大小
    float textSizeBigCount = convertDpToPixel(18);
    //大圆心 文字大小
    float textSizeBigCircle2 = convertDpToPixel(20);
    // label文字大小
    float textSizeLabel = convertDpToPixel(14);
    // label数字字大小
    float textSizeSmallCount = convertDpToPixel(12);
    //线条的宽度
    float lineStrokeWidth = convertDpToPixel(1);
    //阴影的半径
    float shadownRadisu = convertDpToPixel(2);
    //总量的间距
    float paddingTotal = convertDpToPixel(5);
    //下面圆与上面圆的间距
    float paddingBottomCircle = convertDpToPixel(15);
    //下面每一個item的寬度
    float singleItemWidth = convertDpToPixel(61);

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //背景涂成白色
        canvas.drawColor(0xffffffff);
        int width = getWidth();
        int height = getHeight();

        //计算圆心,
        float cx = width / 2;
        float cy = radius + padding;//加上顶部偏移,美观一点

        mPaint.setColor(Color.WHITE);
        float strokeWidth = mPaint.getStrokeWidth();

        //绘制圆环的阴影
//        setLayerType(LAYER_TYPE_SOFTWARE,mPaint);
        mPaint.setShadowLayer(shadownRadisu, 0, shadownRadisu, 0xffAAAAAA);//第一个参数为模糊半径,越大越模糊。 第二个参数是阴影离开文字的x横向距离。 第三个参数是阴影离开文字的Y横向距离。 第四个参数是阴影颜色
        mPaint.setStrokeWidth(border + shadownRadisu / 2);//圆环的着色宽度  1/4大圆环半径的+1/2 外部阴影宽度
        mPaint.setColor(Color.WHITE);
        mPaint.setStyle(Paint.Style.STROKE);//白色 描边
        //内部圆环 + 圆环 +阴影
        canvas.drawCircle(cx, cy, radius - border / 2, mPaint);

        //取消阴影
        mPaint.clearShadowLayer();
        //恢复线框宽度
        mPaint.setStyle(Paint.Style.FILL);

        //对于如果只有2个数据,绘制线条, label
        if (mDataSet.size() == 2) {
            //绘制线条
            float ex = 0, ey = 0;
            // 椭圆方程 (x/a)^2+(y/b)^2=1
            float b = radius + border / 4;//比圆多1/16半径做椭圆短轴
            float a = radius + border;//比圆多1/4半径做椭圆长轴
         /*  paint.setColor(Color.RED);
            for(float x=-a;x<a;x++){
                float y =(float) Math.sqrt(( 1 - x*x/(a*a))*b*b);
                canvas.drawPoint(cx+x,cy+y,paint);
                canvas.drawPoint(cx+x,cy-y,paint);
            }*/
            mPaint.setStrokeWidth(lineStrokeWidth);

            //绘制 2个 线条和文字label
            float tmp = 0;
            for (int i = 0; i < mDataSet.size(); i++) {
                Entry e = mDataSet.get(i);
                int sg = 1;
                //所占圆环中心角度 加上上一个角度如果小于180 画右边设置右对齐
                //这个是为了让上下两个图的文字靠近圆环端能够对齐在一条直线上
                if (tmp + e.angle / 2 > 180) {
                    sg = -1;
                    mPaint.setTextAlign(Paint.Align.RIGHT);
                } else {
                    mPaint.setTextAlign(Paint.Align.LEFT);
                }
                float angle = e.angle;
                if (angle > 180) {
                    angle = 240;
                } else {
                    if (angle > 120)
                        angle = 120;
                }
                //圆环上所占区域中心点到原点 与Y轴的夹角
                angle = (float) ((angle / 2) * Math.PI / 180);
                float k2 = (float) (1 / Math.tan(angle));

                //圆环上所占区域中心点到原点直线与 椭圆的交点坐标
                ex = (float) Math.sqrt(1 / (1 / (a * a) + (k2 * k2) / (b * b)));
                ey = k2 * ex;

                //圆环上所占区域中心点到原点直线与 圆的交点坐标
                float sx = cx + sg * (float) (radius * Math.sin(angle));
                float sy = cy - (float) (radius * Math.cos(angle));

                //最边上(左右边)到文字对齐的线的距离(默认大小为 半径 + 1/8 半径) 既给文字 + 横线(1/8 半径)  留出的宽度
                float linepad = radius + border * 2;

                mPaint.setColor(e.color);
                //圆环上的点到椭圆上的点的斜线
                canvas.drawLine(sx, sy, cx + sg * ex, cy - ey, mPaint);
                //椭圆上的点到文字边上的 横线(border * 2)
                canvas.drawLine(cx + sg * ex, cy - ey, cx + sg * (linepad), cy - ey, mPaint);
                //画文字描述(这里太长会跑出界面,如果需要处理,请参考下面小圆文字的处理)
                mPaint.setColor(0xff5f5f5f);
                mPaint.setTextSize(textSizeLabel);
                canvas.drawText(e.label, cx + sg * (linepad) + sg * textSizeLabel / 2, cy - ey + textSizeLabel * 1 / 3, mPaint);
                tmp += e.angle;//下一个圆环区域中心点的起始角度
            }
        }

        //再绘制白色圆环,把外边缘的白色漏出来(再画一次,)
        mPaint.setColor(Color.WHITE);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(border + shadownRadisu / 2);
        canvas.drawCircle(cx, cy, radius - border / 2, mPaint);

        mPaint.setStrokeWidth(strokeWidth);

        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        canvas.save();
        //剪切内小圆,再绘制扇形,就成了扇形圆环
        Path path = new Path();
        path.addCircle(cx, cy, radius - border, Path.Direction.CCW);
        canvas.clipPath(path, Region.Op.DIFFERENCE);
        float startAngle = -90f;//12点位置
        //内圆环的外接正方形
        RectF arcRect = new RectF(cx - radius, cy - radius, cx + radius, cy + radius);
        for (int i = 0; i < mDataSet.size(); i++) {//绘制扇形圆环
            Entry e = mDataSet.get(i);
            mPaint.setColor(e.color);
            //留1个角度的空白
            canvas.drawArc(arcRect, startAngle, e.angle == 360 ? e.angle : (e.angle - 1), true, mPaint);
            startAngle += e.angle;
        }
        canvas.restore();
        //绘制大圆中心文字数字
        if (!TextUtils.isEmpty(mCenterText)) {
            mPaint.setColor(Color.BLACK);

            mPaint.setTextSize(textSizeBigCount);
            mPaint.setTextAlign(Paint.Align.CENTER);
            canvas.drawText("" + mCount, cx, cy - paddingTotal, mPaint);
            mPaint.setTextSize(textSizeBigCircle2);
            String text = mCenterText;
            //只有一个数据的时候,中间文字为数据类型标签,不是传进来的mCenterText
            if (mDataSet.size() == 1)
                text = mDataSet.get(0).label;
            canvas.drawText(text, cx, cy + textSizeBigCircle2, mPaint);
        }
        // 底部绘制 小圆圈,及label
        if (mDataSet.size() > 2) {
            float scx, scy;
            float sdif = singleItemWidth;

            //最左边到第一个item的距离(留白)
            float sw = (width - mDataSet.size() * sdif) / 2;
            //第一个小圆的圆心
            scy = padding + radius * 2 + paddingBottomCircle + sradius;
            scx = sw + sdif / 2;
            //由于外部限制,这里最多只有6个数据,所以没做多行小圆 的情况处理
            //需求也没有大量数据项的情况,所以其他情况读者自行处理
            for (int i = 0; i < mDataSet.size(); i++) {
                Entry e = mDataSet.get(i);
                mPaint.setColor(e.color);
                canvas.drawCircle(scx, scy, sradius, mPaint);
                mPaint.setColor(Color.WHITE);
                mPaint.setTextSize(textSizeSmallCount);
                canvas.drawText("" + e.value, scx, scy + textSizeSmallCount * 1 / 3, mPaint);
                canvas.save();

                mTextPain.setTextSize(textSizeLabel);
                mTextPain.setTextAlign(Paint.Align.CENTER);
                mTextPain.setColor(0xFF5F5F5F);
                //getWidth()表示绘制多宽后换行
                int end = e.label.length();

                //绘制的文字 色设置固定宽度并自动换行,最多显示两行
                StaticLayout sl = null;
                Class clazz = null;
                try {
                    clazz = Class.forName("android.text.StaticLayout");
                } catch (ClassNotFoundException e1) {
                    e1.printStackTrace();
                }
                Constructor con = null;
                StaticLayout tmp = null;
                try {
                    con = clazz.getConstructor(CharSequence.class, int.class, int.class, TextPaint.class, int.class,
                            Layout.Alignment.class, TextDirectionHeuristic.class, float.class, float.class, boolean.class,
                            TextUtils.TruncateAt.class, int.class, int.class);
                } catch (NoSuchMethodException e1) {
                    e1.printStackTrace();
                }

                try {
                    tmp = (StaticLayout) con.newInstance("" + e.label, 0, end, mTextPain, (int) sdif - 1, Layout.Alignment.ALIGN_NORMAL, TextDirectionHeuristics.FIRSTSTRONG_LTR, 1.0f, 0.0f, true, TextUtils.TruncateAt.MIDDLE, (int) (sdif - 3 * sradius), 2);
                } catch (InstantiationException e1) {
                    e1.printStackTrace();
                } catch (IllegalAccessException e1) {
                    e1.printStackTrace();
                } catch (InvocationTargetException e1) {
                    e1.printStackTrace();
                }
                sl = tmp;

//                StaticLayout sl = new StaticLayout(""+e.label, 0, end, mTextPain, (int)sdif - 1, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true, TextUtils.TruncateAt.MIDDLE, (int)(sdif - 3 * sradius));
                //从0,0开始绘制
                canvas.translate(scx, scy + sradius + paddingTotal);
                sl.draw(canvas);
                canvas.restore();
//                canvas.drawText(""+e.label,scx,scy+sradius*2+paddingTotal,mPaint);
                scx += sdif;
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //这里没有调用父类,因为默认的只是调用了setMeasuredDimension 方法,下面我们自己调用
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int minheight = (int) (padding + radius * 2 + padding);
        if (mDataSet.size() > 2) {
            //加上小面小圆+小圆label文字 + 留白的高度(粗略使用7倍小圆半径),这里是粗略计算,具体自行调节
            minheight += (sradius * 7);
        }

        setMeasuredDimension(
                Math.max(getSuggestedMinimumWidth(),
                        resolveSize(width,
                                widthMeasureSpec)),
                Math.max(getSuggestedMinimumHeight(),
                        resolveSize(minheight,
                                heightMeasureSpec)));
    }

    float convertDpToPixel(float dp) {

        return getResources().getDisplayMetrics().density * dp;

    }

    public static class Entry implements Comparable {
        public String label;
        public int value;
        public float angle;
        public int color;

        public Entry(String label, int value) {
            this.label = label;
            this.value = value;
        }

        @Override
        public int compareTo(@NonNull Object o) {
            Entry e = (Entry) o;
            if (value > e.value)
                return -1;
            if (value < e.value)
                return 1;
            return 0;
        }
    }
}

使用

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.philos.piechartdemo.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#15212121"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#FFFFFF"
            android:orientation="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:drawableLeft="@mipmap/ic_launcher"
                android:drawablePadding="8dp"
                android:gravity="center_vertical"
                android:padding="8dp"
                android:text="单个圆中间显示名字和数量"
                android:textSize="16dp" />

            <com.example.philos.piechartdemo.PieChart
                android:id="@+id/pie_chart"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </LinearLayout>


        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:background="#FFFFFF"
            android:orientation="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:drawableLeft="@mipmap/ic_launcher"
                android:drawablePadding="8dp"
                android:gravity="center_vertical"
                android:padding="8dp"
                android:text="两个显示横线和名称"
                android:textSize="16dp" />

            <com.example.philos.piechartdemo.PieChart
                android:id="@+id/pie_chart1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </LinearLayout>


        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:background="#FFFFFF"
            android:orientation="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:drawableLeft="@mipmap/ic_launcher"
                android:drawablePadding="8dp"
                android:gravity="center_vertical"
                android:padding="8dp"
                android:text="两个显示横线和名称"
                android:textSize="16dp" />

            <com.example.philos.piechartdemo.PieChart
                android:id="@+id/pie_chart12"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:background="#FFFFFF"
            android:orientation="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:drawableLeft="@mipmap/ic_launcher"
                android:drawablePadding="8dp"
                android:gravity="center_vertical"
                android:padding="8dp"
                android:text="超过3个显示小圆"
                android:textSize="16dp" />

            <com.example.philos.piechartdemo.PieChart
                android:id="@+id/pie_chart2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:background="#FFFFFF"
            android:orientation="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:drawableLeft="@mipmap/ic_launcher"
                android:drawablePadding="8dp"
                android:gravity="center_vertical"
                android:padding="8dp"
                android:text="最多6项"
                android:textSize="16dp" />

            <com.example.philos.piechartdemo.PieChart
                android:id="@+id/pie_chart3"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </LinearLayout>
    </LinearLayout>
</ScrollView>
public class MainActivity extends AppCompatActivity {

    private PieChart mPieChart;
    private PieChart mPieChart1;
    private PieChart mPieChart12;
    private PieChart mPieChart2;
    private PieChart mPieChart3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mPieChart = (PieChart) findViewById(R.id.pie_chart);
        mPieChart1 = (PieChart) findViewById(R.id.pie_chart1);
        mPieChart12 = (PieChart) findViewById(R.id.pie_chart12);
        mPieChart2 = (PieChart) findViewById(R.id.pie_chart2);
        mPieChart3 = (PieChart) findViewById(R.id.pie_chart3);

        CompanyInfo companyInfo = new CompanyInfo(20, 0, 0, 0, 0, 0);
        ArrayList tmp = createPieChart(companyInfo);
        mPieChart.setData(tmp, "总共有");

        CompanyInfo companyInfo1 = new CompanyInfo(450, 3, 0, 0, 0, 0);
        ArrayList tmp1 = createPieChart(companyInfo1);
        mPieChart1.setData(tmp1, "总共有");

        CompanyInfo companyInfo12 = new CompanyInfo(370, 0, 0, 600, 0, 0);
        ArrayList tmp12 = createPieChart(companyInfo12);
        mPieChart12.setData(tmp12, "总共有");

        CompanyInfo companyInfo2 = new CompanyInfo(0, 0, 0, 50, 200, 10);
        ArrayList tmp2 = createPieChart(companyInfo2);
        mPieChart2.setData(tmp2, "总共有");

        CompanyInfo companyInfo3 = new CompanyInfo(15000, 10, 190, 7, 210, 80);
        ArrayList tmp3 = createPieChart(companyInfo3);
        mPieChart3.setData(tmp3, "总共有");
    }

    private ArrayList createPieChart(CompanyInfo companyInfo) {
        ArrayList tmp = new ArrayList();
        int count = 0;
        if(companyInfo.trademarks_count > 0) {
            count += companyInfo.trademarks_count;
            tmp.add(new PieChart.Entry("商标",companyInfo.trademarks_count));//trademark
        }
        if(companyInfo.domains_count > 0) {
            count += companyInfo.domains_count;
            tmp.add(new PieChart.Entry("域名",companyInfo.domains_count));//trademark
        }
        if(companyInfo.patents_count > 0) {
            count += companyInfo.patents_count;
            tmp.add(new PieChart.Entry("专利",companyInfo.patents_count));//trademark
        }
        if(companyInfo.soft_count > 0) {
            count += companyInfo.soft_count;
            tmp.add(new PieChart.Entry("软件著作权",companyInfo.soft_count));//trademark
        }
        if(companyInfo.original_count > 0) {
            count += companyInfo.original_count;
            tmp.add(new PieChart.Entry("原创著作权公司资质认证",companyInfo.original_count));//trademark
        }
        if(companyInfo.certificate_count > 0) {
            count += companyInfo.certificate_count;
            tmp.add(new PieChart.Entry("公司资质认证",companyInfo.certificate_count));//trademark
        }
        return tmp;
    }

    class CompanyInfo {
        public int trademarks_count;
        public int domains_count;
        public int patents_count;
        public int soft_count;
        public int original_count;
        public int certificate_count;

        public CompanyInfo(int trademarks_count, int domains_count, int patents_count, int soft_count, int original_count, int certificate_count) {
            this.trademarks_count = trademarks_count;
            this.domains_count = domains_count;
            this.patents_count = patents_count;
            this.soft_count = soft_count;
            this.original_count = original_count;
            this.certificate_count = certificate_count;
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容