1. ConstraintLayout,可能也包括其他自定义View,自定义ViewGroup
- 属性值太繁琐,尝试使用1个属性值代替多个.
使用 app:layout_horizontal_equals="parent / 其他View的id".app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent"
实现方法:
在自定义ConstraintLayout中的onMeasure及onLayout涉及方法中,找到解析子View的layout属性位置,解析我们的自定义属性,并使用.
原始逻辑,伪代码:自定义ConstraintLayout逻辑:void optChildByParams(View child){ *** }//首先解析我们添加的自定义属性值 View child = **; LayoutParams params = child.getLayoutParams(); //解析自定义属性值,然后通过自定义属性值,为'原生属性值赋值' int layoutHorizontalEquals = **; params.startToStart = layoutHorizontalEquals; params.endToEnd = layoutHorizontalEquals; child.setLayoutParams(params); //调用原始逻辑 optChildByParams(child) - ConstraintLayout 中没有多个子View的宽/高 保持所有子View最大/最小的方法.类似 app:layout_width_equals_max_group="id数组 / id".
实现方法:
在自定义 ConstraintLayout 中解析该属性,添加对View数组的宽/高变化的监听,其中每个子View宽高发生变化,都进行比较,类似:<View id="a1" app:layout_width_equals_max_group="@a2"/> <View id="a2" app:layout_width_equals_max_group="@a1"/> class CustomConstraintLayout extends ConstraintLayout { //存储指定ID是否已加入监听 private Set<Integer> monitoredMaxIds = new HashSet<>(); private Set<Integer> monitoredMinIds = new HashSet<>(); private Map<Set<Integer>,Integer> maxWidthForGroup = new HashMap<>(); //解析自定义属性 public void monitorViewGroupForMax(View child){ Set<Integer> idsForMonitor = new HashSet<>(); int layoutWidthEqualsMaxGroup = ***; if(layoutWidthEqualsMaxGroup is Array){ int[] arrays = layoutWidthEqualsMaxGroup.toArray(); idsForMonitor = gainIdsForMonitorMax(arrays); }else{ int currId = child.getId(); int linkedId = layoutWidthEqualsMaxGroup; idsForMonitor = gainIdsForMonitorMax(currId,linkedId); } if(!idsForMonitor.isEmpty()){ monitorViewGroupForMaxLogic(idsForMonitor); } } public void monitorViewGroupForMaxLogic(Set<Integer> ids){ if(maxWidthForGroup.containsKey(ids)){ return; } List<View> views = new ArrayList<>(); for(int id : ids){ views.add(findViewById(id)); } for(View v : views){ v.addWidthChange(new WidthChangeListener(){ void newWidht(int width){ if(maxWidthForGroup.containsKey(ids)){ int groupMaxWidth = maxWidthForGroup.get(ids); if(width <= groupMaxWidth){ //只有自己是最小的,调整自身为'整组宽度'即可 v.setWidth(groupMaxWidth); }else{ //自身现在是最大的,调整'其他组成员的宽度' maxWidthForGroup.put(ids,width); checkAndSetMaxWidthForGroup(ids,width,v.getId()); } }else{ maxWidthForGroup.put(ids,width); //整组只有自己设置了宽度,调整其他组内成员的高度 checkAndSetMaxWidthForGroup(ids,width,v.getId()); } } }); } } public void checkAndSetMaxWidthForGroup(Set<Integer> groupIds,int maxWidth,int currId){ for(int id : groupIds){ if(id != currId){ View v = findViewById(id); if(v.getWidth < maxWidth){ v.setWidth(maxWidth); } } } } }
1. Android端图表/数据可视化
- isometric-contributions 示例图片
- 源于看到Github数据的3D形式展示,Web端使用.搜集了下目前展示复杂/3D类型的产品,绝大多数是JS.例如建筑模型等等展示在Web端已经可以做到很精细的展示,参考阿里云提供的产品 阿里云提供的数据可视化产品示例.
- 基于以上初步了解,在Android上使用Java做复杂模型的绘制/展示,成本是比较高的.可以考虑使用WebView引入d3展示复杂数据.
- Android使用Java可以做到什么程度
- 目前开源的图表库,支持3D/立体效果的很少
- 支持简单3D效果,但是不支持旋转,不具有'近大远小'效果
- 可以自己实现的3D图标库预想特性
- 所有类型图标均支持2D , 3D 展示
- 所有类型图表均支持阴影,所有图表项包括文字支持动画
- 可以自由旋转,缩放,移动
- 3D图表支持近大远小特性
- 近大远小,实质上是要指定'视点',从视点出发对不同位置的绘制做形变/缩放
- 视点:需要指定相对于整体图表的(X,Y,Z 0,0,0)原点的确定位置,横轴,纵轴,高度都要考虑
- 3D图表在旋转时实时刷新
- 支持绕Y轴旋转
- 支持绕X轴旋转
- 支持绕Z轴旋转
- 支持旋转时不同侧面的不同颜色渐变方案/类似光线变化效果
- 增加类似建筑模型图的简单支持
- 不同位置绘制不同的立方体
- 立方体的颜色,不同面的颜色渐变方案