当时自己在用MPChart库做项目的时候遇到的这样一个问题,饼状图的图例实在太多,MPChart所提供的功能无法显示全部的图例(最多也就十几个),柱状图和线图图例不是很多,就是这个饼图的需求有些不一样。然后就在MPChart库里面一直找有没有能动态显示图例的方法,然后就gg了,找半天也没有。最后还是自己写一个吧。
具体代码:
public class LegendView extends LinearLayout {
public static final int HORIZONTAL_TOP = 0; //横向头部
public static final int HORIZONTAL_BOTTOM = 1;//横向底部
public static final int VERTICAL_LEFT = 2;//纵向左侧
public static final int VERTICAL_RIGHT = 3;//纵向右侧
private int direction;//方向
private int leftOffset = 10;//图例列表左侧间距
private int topOffset = 120;//图例列表上侧间距
private int rightOffset = 10;//图例列表右侧间距
private int bottomOffset = 120;//图例列表下侧间距
private Context context;
private View chart;
private LegendViewAdapter adapter;
private RecyclerView recyclerView;
public LegendView(Context context, int direction, View chart) {
super(context, null);
this.direction = direction;
this.context = context;
this.chart = chart;
}
private void initView() {
setOrientation(VERTICAL);
setBackgroundResource(R.color.transparent);
RelativeLayout rootView = new RelativeLayout(getContext());
recyclerView = new RecyclerView(getContext());
recyclerView.setId(Integer.MAX_VALUE - 1000);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
RelativeLayout.LayoutParams chartLayoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
chartLayoutParams.setMargins(leftOffset,topOffset,rightOffset,bottomOffset);
if (direction == HORIZONTAL_TOP || direction == HORIZONTAL_BOTTOM) {
recyclerView.setHorizontalScrollBarEnabled(false);
recyclerView.setVerticalScrollBarEnabled(true);
recyclerView.setFocusable(true);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
if (direction == HORIZONTAL_TOP) {
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
chartLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, recyclerView.getId());
} else {
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
chartLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP, recyclerView.getId());
}
linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setLayoutParams(layoutParams);
} else {
recyclerView.setHorizontalScrollBarEnabled(true);
recyclerView.setVerticalScrollBarEnabled(false);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
if (direction == VERTICAL_LEFT) {
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
chartLayoutParams.addRule(RelativeLayout.RIGHT_OF, recyclerView.getId());
} else {
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
chartLayoutParams.addRule(RelativeLayout.LEFT_OF, recyclerView.getId());
}
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setLayoutParams(layoutParams);
}
recyclerView.setOverScrollMode(OVER_SCROLL_NEVER);
recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
rv.getParent().getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
});
chart.setLayoutParams(chartLayoutParams);
rootView.addView(chart);
rootView.addView(recyclerView);
addView(rootView);
}
public void initData(List legendEntity) {
initView();
adapter = new LegendViewAdapter();
recyclerView.setAdapter(adapter);
adapter.setDatas(legendEntity);
}
public void setOffset(int leftOffset, int topOffset, int rightOffset, int bottomOffset) {
this.leftOffset = leftOffset;
this.topOffset = topOffset;
this.rightOffset = rightOffset;
this.bottomOffset = bottomOffset;
}
}
这么长一串代码看着确实有点多,不需要看懂直接建个类复制进去就行。下面说一下这个类怎么用:
LegendView pieView = new LegendView(pieChart.getContext(), legendDirection, view);//初始化对象,这个view参数是饼状图对象
pieView.setOffset(leftOffset, topOffset, rightOffset, bottomOffset);//设置各个方向的偏移
List legendEntities = new ArrayList<>();
for (int i = 0; i < pieItemList.size(); i++) {//配置每一个图例的属性值,pieItemList是图例名称集合
LegendEntity legendEntity = new LegendEntity();
legendEntity.legend = pieItemList.get(i);//图例名称
legendEntity.textSize = 12;//图例文本字体大小
legendEntity.textColor = Color.BLACK;//图例字体颜色
legendEntity.color = listColor.get(i);//图例颜色,listColor是颜色集合
legendEntities.add(legendEntity);
}
pieView.initData(legendEntities);//设置数据
最后返回的这个pieView就是包含自定义图例列表和饼图的View对象,直接在布局中使用就可以了
还有一个适配器类和一个实体类,如下:
//适配器
public class LegendViewAdapter extends BaseRecyclerAdapter {
@Override
public int getItemLayoutId(int viewType) {
return R.layout.piechart_legend_recycler_item;//这个布局文件很简单,就是两个TextView并排显示,就不贴了
}
@Override
public void setUpData(CommonHolder holder, int position, int viewType, LegendEntity data) {
TextView tvColor = getView(holder, R.id.tv_color);
TextView tvName = getView(holder, R.id.tv_name);
tvName.setTextColor(data.textColor);
tvName.setTextSize(data.textSize);
tvColor.setBackgroundColor(data.color);
tvName.setText(data.legend);
}
}
//实体类
public class LegendEntity {
public String legend;//图例文本
public int color;//图例颜色
public int textColor;//图例字体颜色
public float textSize;//图例字体大小
}
另外我把MPChart这个库二次封装了一下,里面的饼图、雷达图都支持大量的图例显示,有需要的童鞋可以去我的github上瞅一瞅:https://github.com/fjm19960930/ZChart
注:适配器的那个父类是从一个私人库里面搞的,用起来很方便,需要导一下:
implementation 'com.github.zcolin:ZFrame:2.0.9'
implementation 'com.github.zcolin:ZRecyclerView:2.1.5'