文章40 | 阅读 20973 | 点赞0
接口名 | 作用 |
---|---|
setEstimateSizeListener | 设置测量组件的侦听器 |
onEstimateSize | 测量组件的大小以确定宽度和高度 |
setEstimatedSize | 将测量的宽度和高度设置给组件 |
EstimateSpec.getChildSizeWithMode | 基于指定的大小和模式为子组件创建度量规范 |
EstimateSpec.getSize | 从提供的度量规范中提取大小 |
EstimateSpec.getMode | 获取该组件的显示模式 |
addDrawTask | 添加绘制任务 |
onDraw | 通过绘制任务更新组件时调用 |
public class CustomComponent extends Component{
public CustomComponent(Context context) {
super(context);
}
}
public class CustomComponent extends Component implements Component.EstimateSizeListener {
public CustomComponent(Context context) {
super(context);
...
// 设置测量组件的侦听器
setEstimateSizeListener(this);
}
...
@Override
public boolean onEstimateSize(int widthEstimateConfig, int heightEstimateConfig) {
int width = Component.EstimateSpec.getSize(widthEstimateConfig);
int height = Component.EstimateSpec.getSize(heightEstimateConfig);
setEstimatedSize(
Component.EstimateSpec.getChildSizeWithMode(width, width, Component.EstimateSpec.NOT_EXCEED),
Component.EstimateSpec.getChildSizeWithMode(height, height, Component.EstimateSpec.NOT_EXCEED));
return true;
}
}
模式 | 作用 |
---|---|
UNCONSTRAINT | 父组件对子组件没有约束,表示子组件可以任意大小 |
PRECISE | 父组件已确定子组件的大小 |
NOT_EXCEED | 已为子组件确定了最大大小,子组件不能超过指定大小 |
public class CustomComponent extends Component implements Component.DrawTask,Component.EstimateSizeListener {
// 圆环宽度
private static final float CIRCLE_STROKE_WIDTH = 100f;
// 绘制圆环的画笔
private Paint circlePaint;
public CustomComponent(Context context) {
super(context);
// 初始化画笔
initPaint();
// 添加绘制任务
addDrawTask(this);
}
private void initPaint(){
circlePaint = new Paint();
circlePaint.setColor(Color.BLUE);
circlePaint.setStrokeWidth(CIRCLE_STROKE_WIDTH);
circlePaint.setStyle(Paint.Style.STROKE_STYLE);
}
@Override
public void onDraw(Component component, Canvas canvas) {
// 在界面中绘制一个圆心坐标为(500,500),半径为400的圆
canvas.drawCircle(500,500,400,circlePaint);
}
...
}
public class CustomComponent extends Component implements Component.DrawTask, Component.EstimateSizeListener, Component.TouchEventListener {
...
public CustomComponent(Context context) {
...
// 设置TouchEvent响应事件
setTouchEventListener(this);
}
...
@Override
public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
switch (touchEvent.getAction()) {
case TouchEvent.PRIMARY_POINT_DOWN:
circlePaint.setColor(Color.GREEN);
invalidate();
break;
case TouchEvent.PRIMARY_POINT_UP:
circlePaint.setColor(Color.YELLOW);
invalidate();
break;
}
return false;
}
}
@Override
protected void onStart(Intent intent) {
super.onStart(intent);
DirectionalLayout.LayoutConfig config = new DirectionalLayout.LayoutConfig(
DirectionalLayout.LayoutConfig.MATCH_PARENT, DirectionalLayout.LayoutConfig.MATCH_PARENT);
myLayout.setLayoutConfig(config);
CustomComponent customComponent = new CustomComponent(this);
DirectionalLayout.LayoutConfig layoutConfig = new DirectionalLayout.LayoutConfig(1080, 1000);
customComponent.setLayoutConfig(layoutConfig);
myLayout.addComponent(customComponent);
super.setUIContent(myLayout);
}
public class CustomControlBar extends Component implements Component.DrawTask,
Component.EstimateSizeListener, Component.TouchEventListener {
private final static float CIRCLE_ANGLE = 360.0f;
private final static int DEF_UNFILL_COLOR = 0xFF808080;
private final static int DEF_FILL_COLOR = 0xFF1E90FF;
// 圆环轨道颜色
private Color unFillColor;
// 圆环覆盖颜色
private Color fillColor;
// 圆环宽度
private int circleWidth;
// 画笔
private Paint paint;
// 个数
private int count;
// 当前进度
private int currentCount;
// 间隙值
private int splitSize;
// 内圆的正切方形
private RectFloat centerRectFloat;
// 中心绘制的图片
private PixelMap image;
// 原点坐标
private Point centerPoint;
// 进度改变的事件响应
private ProgressChangeListener listener;
public CustomControlBar(Context context) {
super(context);
paint = new Paint();
initData();
setEstimateSizeListener(this);
setTouchEventListener(this);
addDrawTask(this);
}
// 初始化属性值
private void initData() {
unFillColor = new Color(DEF_UNFILL_COLOR);
fillColor = new Color(DEF_FILL_COLOR);
count = 10;
currentCount = 2;
splitSize = 15;
circleWidth = 60;
centerRectFloat = new RectFloat();
image = Utils.createPixelMapByResId(ResourceTable.Media_icon, getContext()).get();
listener = null;
}
@Override
public boolean onEstimateSize(int widthEstimateConfig, int heightEstimateConfig) {
int width = Component.EstimateSpec.getSize(widthEstimateConfig);
int height = Component.EstimateSpec.getSize(heightEstimateConfig);
setEstimatedSize(
Component.EstimateSpec.getChildSizeWithMode(width, width, Component.EstimateSpec.PRECISE),
Component.EstimateSpec.getChildSizeWithMode(height, height, Component.EstimateSpec.PRECISE)
);
return true;
}
@Override
public void onDraw(Component component, Canvas canvas) {
paint.setAntiAlias(true);
paint.setStrokeWidth(circleWidth);
paint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);
paint.setStyle(Paint.Style.STROKE_STYLE);
int width = getWidth();
int center = width / 2;
centerPoint = new Point(center, center);
int radius = center - circleWidth / 2;
drawCount(canvas, center, radius);
int inRadius = center - circleWidth;
double length = inRadius - Math.sqrt(2) * 1.0f / 2 * inRadius;
centerRectFloat.left = (float) (length + circleWidth);
centerRectFloat.top = (float) (length + circleWidth);
centerRectFloat.bottom = (float) (centerRectFloat.left + Math.sqrt(2) * inRadius);
centerRectFloat.right = (float) (centerRectFloat.left + Math.sqrt(2) * inRadius);
// 如果图片比较小,那么根据图片的尺寸放置到正中心
Size imageSize = image.getImageInfo().size;
if (imageSize.width < Math.sqrt(2) * inRadius) {
centerRectFloat.left = (float) (centerRectFloat.left + Math.sqrt(2) * inRadius * 1.0f / 2 - imageSize.width * 1.0f / 2);
centerRectFloat.top = (float) (centerRectFloat.top + Math.sqrt(2) * inRadius * 1.0f / 2 - imageSize.height * 1.0f / 2);
centerRectFloat.right = centerRectFloat.left + imageSize.width;
centerRectFloat.bottom = centerRectFloat.top + imageSize.height;
}
canvas.drawPixelMapHolderRect(new PixelMapHolder(image), centerRectFloat, paint);
}
private void drawCount(Canvas canvas, int centre, int radius) {
float itemSize = (CIRCLE_ANGLE - count * splitSize) / count;
RectFloat oval = new RectFloat(centre - radius, centre - radius, centre + radius, centre + radius);
paint.setColor(unFillColor);
for (int i = 0; i < count; i++) {
Arc arc = new Arc((i * (itemSize + splitSize)) - 90, itemSize, false);
canvas.drawArc(oval, arc, paint);
}
paint.setColor(fillColor);
for (int i = 0; i < currentCount; i++) {
Arc arc = new Arc((i * (itemSize + splitSize)) - 90, itemSize, false);
canvas.drawArc(oval, arc, paint);
}
}
@Override
public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
switch (touchEvent.getAction()) {
case TouchEvent.PRIMARY_POINT_DOWN:
case TouchEvent.POINT_MOVE: {
this.getContentPositionX();
MmiPoint absPoint = touchEvent.getPointerPosition(touchEvent.getIndex());
Point point = new Point(absPoint.getX() - getContentPositionX(),
absPoint.getY() - getContentPositionY());
double angle = calcRotationAngleInDegrees(centerPoint, point);
double multiple = angle / (CIRCLE_ANGLE / count);
if ((multiple - (int) multiple) > 0.4) {
currentCount = (int) multiple + 1;
} else {
currentCount = (int) multiple;
}
if (listener != null) {
listener.onProgressChangeListener(currentCount);
}
invalidate();
break;
}
}
return false;
}
public interface ProgressChangeListener {
void onProgressChangeListener(int Progress);
}
// 计算centerPt到targetPt的夹角,单位为度。返回范围为[0, 360),顺时针旋转。
private double calcRotationAngleInDegrees(Point centerPt, Point targetPt) {
double theta = Math.atan2(targetPt.getPointY()
- centerPt.getPointY(), targetPt.getPointX()
- centerPt.getPointX());
theta += Math.PI / 2.0;
double angle = Math.toDegrees(theta);
if (angle < 0) {
angle += CIRCLE_ANGLE;
}
return angle;
}
public Color getUnFillColor() {
return unFillColor;
}
public CustomControlBar setUnFillColor(Color unFillColor) {
this.unFillColor = unFillColor;
return this;
}
public Color getFillColor() {
return fillColor;
}
public CustomControlBar setFillColor(Color fillColor) {
this.fillColor = fillColor;
return this;
}
public int getCircleWidth() {
return circleWidth;
}
public CustomControlBar setCircleWidth(int circleWidth) {
this.circleWidth = circleWidth;
return this;
}
public int getCount() {
return count;
}
public CustomControlBar setCount(int count) {
this.count = count;
return this;
}
public int getCurrentCount() {
return currentCount;
}
public CustomControlBar setCurrentCount(int currentCount) {
this.currentCount = currentCount;
return this;
}
public int getSplitSize() {
return splitSize;
}
public CustomControlBar setSplitSize(int splitSize) {
this.splitSize = splitSize;
return this;
}
public PixelMap getImage() {
return image;
}
public CustomControlBar setImage(PixelMap image) {
this.image = image;
return this;
}
public void build() {
invalidate();
}
public void setProgressChangerListener(ProgressChangeListener listener) {
this.listener = listener;
}
}
public class Utils {
private static final HiLogLabel TAG = new HiLogLabel(3, 0xD001100, "Utils");
private static byte[] readResource(Resource resource) {
final int bufferSize = 1024;
final int ioEnd = -1;
byte[] byteArray;
byte[] buffer = new byte[bufferSize];
try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
while (true) {
int readLen = resource.read(buffer, 0, bufferSize);
if (readLen == ioEnd) {
HiLog.error(TAG, "readResource finish");
byteArray = output.toByteArray();
break;
}
output.write(buffer, 0, readLen);
}
} catch (IOException e) {
HiLog.debug(TAG, "readResource failed " + e.getLocalizedMessage());
return new byte[0];
}
HiLog.debug(TAG, "readResource len: " + byteArray.length);
return byteArray;
}
/**
* Creates a {@code PixelMap} object based on the image resource ID.
* <p>
* This method only loads local image resources. If the image file does not exist or the loading fails,
* {@code null} is returned.
*
* @param resourceId Indicates the image resource ID.
* @param slice Indicates the Context.
* @return Returns the image.
*/
public static Optional<PixelMap> createPixelMapByResId(int resourceId, Context slice) {
ResourceManager manager = slice.getResourceManager();
if (manager == null) {
return Optional.empty();
}
try (Resource resource = manager.getResource(resourceId)) {
if (resource == null) {
return Optional.empty();
}
ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
srcOpts.formatHint = "image/png";
ImageSource imageSource = ImageSource.create(readResource(resource), srcOpts);
if (imageSource == null) {
return Optional.empty();
}
ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
decodingOpts.desiredSize = new Size(0, 0);
decodingOpts.desiredRegion = new Rect(0, 0, 0, 0);
decodingOpts.desiredPixelFormat = PixelFormat.ARGB_8888;
return Optional.of(imageSource.createPixelmap(decodingOpts));
} catch (NotExistException | IOException e) {
return Optional.empty();
}
}
}
@Override
protected void onStart(Intent intent) {
super.onStart(intent);
DirectionalLayout.LayoutConfig config = new DirectionalLayout.LayoutConfig(
DirectionalLayout.LayoutConfig.MATCH_PARENT, DirectionalLayout.LayoutConfig.MATCH_PARENT);
myLayout.setLayoutConfig(config);
// 在此创建自定义组件,并可设置其属性
CustomControlBar controlBar = new CustomControlBar(this);
controlBar.setClickable(true);
DirectionalLayout.LayoutConfig layoutConfig = new DirectionalLayout.LayoutConfig(
600, 600);
controlBar.setLayoutConfig(layoutConfig);
ShapeElement element = new ShapeElement();
element.setRgbColor(new RgbColor(0, 0, 0));
controlBar.setBackground(element);
// 将此组件添加至布局,并在界面中显示
myLayout.addComponent(controlBar);
super.setUIContent(myLayout);
}
接口名 | 作用 |
---|---|
setEstimateSizeListener | 设置测量组件的侦听器 |
onEstimateSize | 测量组件的大小以确定宽度和高度 |
setEstimatedSize | 将测量的宽度和高度设置给组件 |
EstimateSpec.getChildSizeWithMode | 基于指定的大小和模式为子组件创建度量规范 |
EstimateSpec.getSize | 从提供的度量规范中提取大小 |
EstimateSpec.getMode | 获取该组件的显示模式 |
arrange | 相对于容器组件设置组件的位置和大小 |
接口名 | 作用 |
---|---|
setArrangeListener | 设置容器组件布局子组件的侦听器 |
onArrange | 通知容器组件在布局时设置子组件的位置和大小 |
public class CustomLayout extends ComponentContainer {
public CustomLayout(Context context) {
super(context);
}
}
public class CustomLayout extends ComponentContainer
implements ComponentContainer.EstimateSizeListener {
...
public CustomLayout(Context context) {
...
setEstimateSizeListener(this);
}
@Override
public boolean onEstimateSize(int widthEstimatedConfig, int heightEstimatedConfig) {
// 通知子组件进行测量
measureChildren(widthEstimatedConfig, heightEstimatedConfig);
int width = Component.EstimateSpec.getSize(widthEstimatedConfig);
// 关联子组件的索引与其布局数据
for (int idx = 0; idx < getChildCount(); idx++) {
Component childView = getComponentAt(idx);
addChild(childView, idx, width);
}
setEstimatedSize(
Component.EstimateSpec.getChildSizeWithMode(maxWidth, widthEstimatedConfig, 0),
Component.EstimateSpec.getChildSizeWithMode(maxHeight, heightEstimatedConfig, 0));
return true;
}
private void measureChildren(int widthEstimatedConfig, int heightEstimatedConfig) {
for (int idx = 0; idx < getChildCount(); idx++) {
Component childView = getComponentAt(idx);
if (childView != null) {
measureChild(childView, widthEstimatedConfig, heightEstimatedConfig);
}
}
}
private void measureChild(Component child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) {
ComponentContainer.LayoutConfig lc = child.getLayoutConfig();
int childWidthMeasureSpec = EstimateSpec.getChildSizeWithMode(
lc.width, parentWidthMeasureSpec, EstimateSpec.UNCONSTRAINT);
int childHeightMeasureSpec = EstimateSpec.getChildSizeWithMode(
lc.height, parentHeightMeasureSpec, EstimateSpec.UNCONSTRAINT);
child.estimateSize(childWidthMeasureSpec, childHeightMeasureSpec);
}
}
private int xx = 0;
private int yy = 0;
private int maxWidth = 0;
private int maxHeight = 0;
private int lastHeight = 0;
// 子组件索引与其布局数据的集合
private final Map<Integer, Layout> axis = new HashMap<>();
private static class Layout {
int positionX = 0;
int positionY = 0;
int width = 0;
int height = 0;
}
...
private void invalidateValues() {
xx = 0;
yy = 0;
maxWidth = 0;
maxHeight = 0;
axis.clear();
}
private void addChild(Component component, int id, int layoutWidth) {
Layout layout = new Layout();
layout.positionX = xx + component.getMarginLeft();
layout.positionY = yy + component.getMarginTop();
layout.width = component.getEstimatedWidth();
layout.height = component.getEstimatedHeight();
if ((xx + layout.width) > layoutWidth) {
xx = 0;
yy += lastHeight;
lastHeight = 0;
layout.positionX = xx + component.getMarginLeft();
layout.positionY = yy + component.getMarginTop();
}
axis.put(id, layout);
lastHeight = Math.max(lastHeight, layout.height + component.getMarginBottom());
xx += layout.width + component.getMarginRight();
maxWidth = Math.max(maxWidth, layout.positionX + layout.width);
maxHeight = Math.max(maxHeight, layout.positionY + layout.height);
}
@Override
protected void onStart(Intent intent) {
super.onStart(intent);
DirectionalLayout.LayoutConfig config = new DirectionalLayout.LayoutConfig(
DirectionalLayout.LayoutConfig.MATCH_PARENT, DirectionalLayout.LayoutConfig.MATCH_PARENT);
myLayout.setLayoutConfig(config);
CustomLayout customLayout = new CustomLayout(this);
for (int idx = 0; idx < 15; idx++) {
customLayout.addComponent(getComponent(idx + 1));
}
ShapeElement shapeElement = new ShapeElement();
shapeElement.setRgbColor(COLOR_LAYOUT_BG);
customLayout.setBackground(shapeElement);
LayoutConfig layoutConfig = new LayoutConfig(LayoutConfig.MATCH_PARENT,
LayoutConfig.MATCH_CONTENT);
customLayout.setLayoutConfig(layoutConfig);
myLayout.addComponent(customLayout);
super.setUIContent(myLayout);
}
// 创建子组件
private Component getComponent(int idx) {
Button button = new Button(getContext());
ShapeElement shapeElement = new ShapeElement();
shapeElement.setRgbColor(COLOR_BTN_BG);
button.setBackground(shapeElement);
button.setTextColor(Color.WHITE);
LayoutConfig layoutConfig = new LayoutConfig(300, 100);
if (idx == 1) {
layoutConfig = new LayoutConfig(1080, 200);
button.setText("1080 * 200");
} else if (idx == 6) {
layoutConfig = new LayoutConfig(500, 100);
button.setText("500 * 100");
} else if (idx == 8) {
layoutConfig = new LayoutConfig(600, 600);
button.setText("600 * 600");
} else {
button.setText("Item" + idx);
}
layoutConfig.setMargins(10, 10, 10, 10);
button.setLayoutConfig(layoutConfig);
return button;
}
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/Forever_wj/article/details/118279691
内容来源于网络,如有侵权,请联系作者删除!