0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

鸿蒙系统如何设置自定义下拉刷新控件

OpenHarmony技术社区 来源: 鸿蒙技术社区 作者:中软国际 2021-09-13 09:24 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

Ohos-MaterialRefreshLayout 是一个自定义 Material 风格下拉刷新控件,支持设置水波纹效果,支持下拉刷新侵入式和非侵入式,初始化自动刷新及上滑加载更多,支持刷新头部自定义图案,上拉加载更多等。

该控件一般配合 ListContainer 使用,因涉及事件分发操作,本库中使用了三方控件 NestedListContainer、事件分发等方便处理事件拦截分发事件。

自定义控件结构

MaterialRefreshLayout 控件,首先初始化设置头部、脚部布局,在手势下滑时显示头部布局,动态设置头部高度,展示下拉刷新效果,在页面底部向上滑动时显示脚部布局,展示上拉加载更多效果,松手时图形即开始旋转动画。

下拉圆形转动风格 MaterialRefreshLayout:

MaterialRefreshLayout 包含自定义头部布局 MaterialHeaderView 和脚部布局 MaterialFooterView。

头部 MaterialHeaderView 包含圆形转动条 CircleProgressBar 和下拉波纹 MaterialWaveView。

脚部布局 MaterialFooterView 同头部结构一致,包含圆形转动条 CircleProgressBar 和下拉波纹 MaterialWaveView。

CircleProgressBar 包含有自定义图形的 MaterialProgressDrawable,设置圆形的转动图案。

下拉自定义笑脸风格 MaterialRefreshLayout:

MaterialRefreshLayout 包含 SunLayout 头部布局和脚部布局 MaterialFooterView。

SunLayout 头部包含滚动短线 SunLineView 和笑脸 SunFaceView。

当有手势下滑时,自定义短线 SunLineView,开始旋转动画,监听刷新动作,在 onSizeChanged 中动态改变图形大小。

当手势向下滑动时,自定义笑脸图形 SunFaceView,监听刷新动作,在 onSizeChanged 中动态改变图形大小。

代码实现解读

首先在拦截事件中根据手指的滑动距离,设置自定义头部布局 MaterialHeaderView 可见,底部向上滑动时,当滑到页面底部,设置脚部布局 MaterialFooterView 可见。

①事件分发 onInterceptTouchEvent 中设置头、脚布局可见

在拦截事件 onInterceptTouchEvent 中,手指移动 TouchEvent.POINT_MOVE 时,根据滑动距离及是否是在头部的滑动。

设置头部自定义 headerview 是否显示,再根据向上滑动距离是否小于 0 及是否滑动到底部加载底部 footerview。

代码如下:

case TouchEvent.POINT_MOVE:

float currentY = ev.getPointerPosition(0).getY();

Float dy= new BigDecimal(currentY).subtract(new BigDecimal(mTouchY)).floatValue();

if (dy 》 0 && !canChildScrollUp()) {

if (mMaterialHeaderView != null) {

mMaterialHeaderView.setVisibility(Component.VISIBLE);

mMaterialHeaderView.onBegin(this);

} else if (mSunLayout != null) {

mSunLayout.setVisibility(Component.VISIBLE);

mSunLayout.onBegin(this);

}

return true;

} else if (dy 《 0 && !canChildScrollDown() && isLoadMore) {

if (mMaterialFooterView != null && !isLoadMoreing) {

soveLoadMoreLogic();

}

return false;

}

break;

上一步完成后,紧接着就是在触摸事件中动态设置头部布局高度,水波纹高度,滑到最大距离时,设置为控件本身高度。

②事件触摸 onTouchEvent 中设置高度

在触摸事件 onTouchEvent 中,当手指下滑,onTouchEvent 中设置头部自定义 headerview 的高度,随着下滑距离增加,动态设置水波纹高度,当头部为侵入式时,设置 component 向下平移。

代码如下:

case TouchEvent.POINT_MOVE:

mCurrentY = e.getPointerPosition(0).getY();

float dy = new BigDecimal(mCurrentY).subtract(new BigDecimal(mTouchY)).floatValue();

dy = Math.min(mWaveHeight * 2, dy);

dy = Math.max(0, dy);

if (mChildView != null) {

float offsetY = dy / 2;

float fraction = offsetY / mHeadHeight;

if (mMaterialHeaderView != null) {

mMaterialHeaderView.setHeight((int) offsetY);

mMaterialHeaderView.postLayout();

mMaterialHeaderView.onPull(this, fraction);

} else if (mSunLayout != null) {

mSunLayout.setHeight((int) offsetY);

mSunLayout.postLayout();

mSunLayout.startSunLineAnim(this);

mSunLayout.onPull(this, fraction);

}

if (!isOverlay)

mChildView.setTranslationY(offsetY);

}

在松手时,监听抬起事件 TouchEvent.PRIMARY_POINT_UP,当头部 headerview 高度大于原有高度时,将头部设置为刷新中状态。

代码如下:

if (mMaterialHeaderView.getLayoutConfig().height 》 mHeadHeight) {

updateListener();

mMaterialHeaderView.setHeight((int) mHeadHeight);

mMaterialHeaderView.postLayout();

}

再接下来就是完成自定义头部控件的布局,并在下拉接口方法中设置下拉时的缩放,透明度等状态。

③自定义头部 MaterialHeaderView

自定义 MaterialHeaderView 由 MaterialWaveView 和 CircleProgressBar 两个自定义 Component 组合成,实现 MaterialHeadListener 接口。

onBegin 方法中设置 materialWaveView 的起始状态,circleProgressBar 缩放大小,透明度等。

代码如下:

@Overridepublic void onBegin(MaterialRefreshLayout materialRefreshLayout) {

if (materialWaveView != null) {

materialWaveView.onBegin(materialRefreshLayout);

}

if (circleProgressBar != null) {

circleProgressBar.setScaleX(0.001f);

circleProgressBar.setScaleY(0.001f);

circleProgressBar.onBegin(materialRefreshLayout);

}

}

onPull 方法中设置 materialWaveView 的下拉状态,circleProgressBar 缩放大小,透明度等。

代码如下:

@Overridepublic void onPull(MaterialRefreshLayout materialRefreshLayout, float fraction) {

if (materialWaveView != null) {

materialWaveView.onPull(materialRefreshLayout, fraction);

}

if (circleProgressBar != null) {

circleProgressBar.onPull(materialRefreshLayout, fraction);

float a = Util.limitValue(1, fraction);

circleProgressBar.setScaleX(a);

circleProgressBar.setScaleY(a);

circleProgressBar.setAlpha(a);

}

}

设置刷新中 onRefreshing 状态。代码如下:

@Overridepublic void onRefreshing(MaterialRefreshLayout materialRefreshLayout) {

if (materialWaveView != null) {

materialWaveView.onRefreshing(materialRefreshLayout);

}

if (circleProgressBar != null) {

circleProgressBar.onRefreshing(materialRefreshLayout);

}

}

onComlete 刷新完成后自定义 Component 的状态初始化,代码如下:

@Override

public void onComlete(MaterialRefreshLayout materialRefreshLayout) {

if (materialWaveView != null) {

materialWaveView.onComlete(materialRefreshLayout);

}

if (circleProgressBar != null) {

circleProgressBar.onComlete(materialRefreshLayout);

circleProgressBar.setTranslationY(0);

circleProgressBar.setScaleX(0);

circleProgressBar.setScaleY(0);

}

}

头部布局完成后,接下来就是实现自定义脚部布局实现。

④自定义脚部 MaterialFooterView

自定义 MaterialFooterView 由 MaterialWaveView 和 CircleProgressBar 两个自定义 Component 组合成,实现 MaterialHeadListener 接口。基本同 MaterialHeaderView 一致,接口实现方法设置内容相同。

onBegin 方法中设置 materialWaveView 的起始状态,circleProgressBar 缩放 1,透明度等。

代码如下:

@Overridepublic void onBegin(MaterialRefreshLayout materialRefreshLayout) {

if (materialWaveView != null) {

materialWaveView.onBegin(materialRefreshLayout);

}

if (circleProgressBar != null) {

circleProgressBar.onBegin(materialRefreshLayout);

circleProgressBar.setScaleX(1);

circleProgressBar.setScaleY(1);

}

}

onPull 方法中设置 materialWaveView 的下拉状态,circleProgressBar 缩放 1,透明度等。

代码如下:

@Overridepublic void onPull(MaterialRefreshLayout materialRefreshLayout, float fraction) {

if (materialWaveView != null) {

materialWaveView.onPull(materialRefreshLayout, fraction);

}

if (circleProgressBar != null) {

circleProgressBar.onPull(materialRefreshLayout, fraction);

float a = Util.limitValue(1, fraction);

circleProgressBar.setScaleX(1);

circleProgressBar.setScaleY(1);

circleProgressBar.setAlpha(a);

}

}

设置刷新中 onRefreshing 状态。代码如下:

@Overridepublic void onRefreshing(MaterialRefreshLayout materialRefreshLayout) {

if (materialWaveView != null) {

materialWaveView.onRefreshing(materialRefreshLayout);

}

if (circleProgressBar != null) {

circleProgressBar.onRefreshing(materialRefreshLayout);

}

}

onComlete 刷新完成后自定义 Component 的状态初始化,代码如下:

@Overridepublic void onComlete(MaterialRefreshLayout materialRefreshLayout) {

if (materialWaveView != null) {

materialWaveView.onComlete(materialRefreshLayout);

}

if (circleProgressBar != null) {

circleProgressBar.onComlete(materialRefreshLayout);

circleProgressBar.setTranslationY(0);

circleProgressBar.setScaleX(0);

circleProgressBar.setScaleY(0);

}

}

头部、脚部布局都完成后,就开始要完成头部和脚部布局里面的自定义组件,首先从头部布局中的自定义组件开始。

前面讲到头部由圆形转动条 CircleProgressBar 和下拉波纹 MaterialWaveView 组成,先开始绘制波浪纹 MaterialWaveView,实现 MaterialHeadListener 接口,接口回调中设置组件的状态。

⑤自定义 MaterialWaveView

初始化画笔设置,添加 addDrawTask 任务,onDraw 方法中绘制下拉区域图形,并填充颜色。

代码如下:

@Overridepublic void onDraw(Component component, Canvas canvas) {

path.reset();

paint.setColor(new Color(color));

path.lineTo(0, headHeight);

path.quadTo(getEstimatedWidth() / (float) 2, headHeight + waveHeight, getEstimatedWidth(), headHeight);

path.lineTo(getEstimatedWidth(), 0);

canvas.drawPath(path, paint);

}

实现 MaterialHeadListener 接口,监听各下拉方法的回调,当有下拉的情形时,改变下拉区域状态。下拉时在 onPull 中,设置下拉区域 header 高度及 wave 高度。

刷新中 onRefreshing,加载数值动画并动态改变 wave 高度。结束 onComlete 中,加载数值动画动态改变 head 的高度。代码如下:

下拉时:

@Overridepublic void onPull(MaterialRefreshLayout br, float fraction) {

setHeadHeight((int) (Util.dip2px(getContext(), DefaulHeadHeight) * Util.limitValue(1, fraction)));

setWaveHeight((int) (Util.dip2px(getContext(), DefaulWaveHeight) * Math.max(0, new BigDecimal(fraction).subtract(new BigDecimal(1)).floatValue())));

invalidate();

}

刷新时:

@Override

public void onRefreshing(MaterialRefreshLayout br) {

setHeadHeight((int) (Util.dip2px(getContext(), DefaulHeadHeight)));

int waveHeight = getWaveHeight();

AnimatorValue animator = new AnimatorValue();

animator.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {

@Override

public void onUpdate(AnimatorValue animatorValue, float value) {

setWaveHeight(getIntValue((1 - (double) value) * waveHeight));

invalidate();

}

});

animator.setCurveType(Animator.CurveType.BOUNCE);

animator.setDuration(200);

animator.start();

}

结束时:

@Override

public void onComlete(MaterialRefreshLayout br) {

waveHeight = 0;

AnimatorValue animator = new AnimatorValue();

animator.setDuration(200);

animator.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {

@Override

public void onUpdate(AnimatorValue animatorValue, float value) {

headHeight = getIntValue((1 - (double) value) * headHeight);

invalidate();

}

});

animator.start();

}

上一步完成后接下来开始实现头部圆形转动的 CircleProgressBar,并设置图案的自定义 ShapeElement 图形,配合手势操作,下拉时设置图形动态大小,松手时旋转刷新。

⑥自定义 CircleProgressBar

自定义圆形转动 CircleProgressBar,设置自定义背景 MaterialProgressDrawable,实现 MaterialHeadListener 接口。

根据下拉状态设置圆形 MaterialProgressDrawable 旋转角度,释放手势时开始动画,结束后停止旋转并初始化状态等。

代码如下:

@Overridepublic void onPull(MaterialRefreshLayout materialRefreshLayout, float fraction) {

if (mProgressDrawable != null)

mProgressDrawable.setProgressRotation(fraction);

invalidate();

}

@OverridePublic void onRefreshing(MaterialRefreshLayout materialRefreshLayout) {

if (mProgressDrawable != null) {

mProgressDrawable.onStart();

}

}

@Overridepublic void onComlete(MaterialRefreshLayout materialRefreshLayout) {

if (mProgressDrawable != null) {

mProgressDrawable.onStop();

}

setVisibility(Component.INVISIBLE);

}

自定义 MaterialProgressDrawable 设置 CircleProgressBar 的背景,首先构造方法中初始化圆形 Ring 和旋转动画,设置画笔颜色,宽度,大小,在 drawToCanvas 中绘制圆形 Ring。

当有手势操作时调用 onStart 方法中的旋转动画,开始旋转。在 Ring 类 draw 方法中,根据起始旋转角度绘制圆形圈圈及三角箭头。

代码如下:

public void draw(Canvas c, Rect bounds) {

final RectFloat arcBounds = mTempBounds;

arcBounds.modify(bounds);

arcBounds.left = new BigDecimal(arcBounds.left).add(new BigDecimal(mStrokeInset)).floatValue();

arcBounds.top = new BigDecimal(arcBounds.top).add(new BigDecimal(mStrokeInset)).floatValue();

arcBounds.right = new BigDecimal(arcBounds.right).subtract(new BigDecimal(mStrokeInset)).floatValue();

arcBounds.bottom = new BigDecimal(arcBounds.bottom).subtract(new BigDecimal(mStrokeInset)).floatValue();

final float startAngle = new BigDecimal(mStartTrim).add(new BigDecimal(mRotation)).floatValue() * 360;

final float endAngle = new BigDecimal(mEndTrim).add(new BigDecimal(mRotation)).floatValue() * 360;

float sweepAngle = new BigDecimal(endAngle).subtract(new BigDecimal(startAngle)).floatValue();

mPaint.setColor(Color.RED);

c.drawArc(arcBounds, new Arc(startAngle, sweepAngle, false), mPaint);

drawTriangle(c, startAngle, sweepAngle, bounds);

if (mAlpha 《 255) {

mCirclePaint.setColor(new Color(mBackgroundColor));

mCirclePaint.setAlpha(255 - mAlpha);

c.drawCircle(bounds.getCenterX(), bounds.getCenterY(), bounds.getWidth() / (float) 2,

mCirclePaint);

}

}

上述基本上就完成了 Material 风格下拉刷新带水波纹,带转动 progressbar 的实现步骤,紧接着讲一讲下拉自定义笑脸的另外一种刷新风格,实际上就是重新定义了刷新头部的图形,在这里也可以自己尝试替换成其它不同的图形。

⑦自定义头部 SunLayout 布局

自定义头部 SunLayout 由 SunFaceView 和 SunLineView 组成,SunFaceView 为自定义笑脸,SunLineView 为自定义笑脸周围短线。

SunLayout 实现了 MaterialHeadListener 接口,开始状态 onBegin 时缩放从零到有,下拉 onPull 时,设置 SunView 和 LineView 的大小,缩放等。代码如下:

开始时:

@Override

public void onBegin(MaterialRefreshLayout materialRefreshLayout) {

setScaleX(0.001f);

setScaleY(0.001f);

}

下拉时:

@Overridepublic void onPull(MaterialRefreshLayout materialRefreshLayout, float fraction) {

float a = Util.limitValue(1, fraction);

if (a 》= 0.7) {

mLineView.setVisibility(VISIBLE);

} else {

mLineView.setVisibility(HIDE);

}

mSunView.setPerView(mSunRadius, a);

mLineView.setLineWidth(mLineWidth);

setScaleX(a);

setScaleY(a);

setAlpha(a);

}

自定义笑脸 SunFaceView,自定义短线 SunLineView。

SunLineView 继承 Component 实现 Component.DrawTask, Component.EstimateSizeListener 接口,构造方法中初始化 Paint,onEstimateSize 中测量宽高,onDraw 中绘制线条。代码如下:

测量时:

@Overridepublic boolean onEstimateSize(int widthMeasureSpec, int heightMeasureSpec) {

HiLog.info(Contants.LABEL, “onMeasure”);

int widthMode = EstimateSpec.getMode(widthMeasureSpec);

int widthSize = EstimateSpec.getSize(widthMeasureSpec);

int heightMode = EstimateSpec.getMode(heightMeasureSpec);

int heightSize = EstimateSpec.getSize(heightMeasureSpec);

int width;

int height;

if (widthMode == EstimateSpec.PRECISE) {

width = widthSize;

} else {

width = (mSunRadius + mFixLineHeight + mLineHeight) * 2 + getPaddingRight() + getPaddingLeft();

}

if (heightMode == EstimateSpec.PRECISE) {

height = heightSize;

} else {

height = (mSunRadius + mFixLineHeight + mLineHeight) * 2 + getPaddingTop() + getPaddingBottom();

}

setEstimatedSize(width, height);

mWidth = width;

mHeight = height;

return false;

}

画线条:

private void drawLines(Canvas canvas) {

for (int i = 0; i 《= 360; i++) {

if (i % mLineLevel == 0) {

mLineLeft = mWidth / 2 - mLineWidth / 2;

mLineTop = mHeight / 2 - mSunRadius - mFixLineHeight;

mLineBottom = mLineTop + mLineHeight;

}

canvas.save();

canvas.rotate(i, mWidth / (float) 2, mHeight / (float) 2);

canvas.drawLine(mLineLeft, mLineTop, mLineLeft, mLineBottom, mLinePaint);

canvas.restore();

}

}

代码参考:

https://gitee.com/chinasoft5_ohos/Ohos-MaterialRefreshLayout

作者:卢经纬

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 操作系统
    +关注

    关注

    37

    文章

    7329

    浏览量

    128642
  • 中软国际
    +关注

    关注

    0

    文章

    715

    浏览量

    8089
  • 鸿蒙系统
    +关注

    关注

    183

    文章

    2642

    浏览量

    69345
  • HarmonyOS
    +关注

    关注

    80

    文章

    2146

    浏览量

    35580

原文标题:鸿蒙下拉刷新组件,这个最好用!

文章出处:【微信号:gh_834c4b3d87fe,微信公众号:OpenHarmony技术社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    无图形界面模式下自定义检查工具的应用

    此前文章已介绍 ANSA 中的自定义检查工具。本文将探讨该功能在无图形界面(No-GUI)模式下的应用,旨在满足标准化工作流程的需求,适用于需要高度自动化的前处理场景。通过集成自定义检查,用户可实现工作流程的高效自动化运行。
    的头像 发表于 11-30 14:13 300次阅读
    无图形界面模式下<b class='flag-5'>自定义</b>检查工具的应用

    大彩讲堂:VisualTFT软件如何自定义圆形进度条

    VisualTFT软件如何自定义圆形进度条
    的头像 发表于 07-07 17:10 1220次阅读
    大彩讲堂:VisualTFT软件如何<b class='flag-5'>自定义</b>圆形进度条

    KiCad 中的自定义规则(KiCon 演讲)

    “  Seth Hillbrand 在 KiCon US 2025 上为大家介绍了 KiCad 的规则系统,并详细讲解了自定义规则的设计与实例。  ”   演讲主要围绕 加强 KiCad 中的自定义
    的头像 发表于 06-16 11:17 1470次阅读
    KiCad 中的<b class='flag-5'>自定义</b>规则(KiCon 演讲)

    HarmonyOS实战:自定义时间选择器

    前言 最近在日常鸿蒙开发过程中,经常会使用一些时间选择器,鸿蒙官方提供的时间选择器满足不了需求,所以自己动手自定义一些经常会使用到的时间选择器,希望能帮到你,建议点赞收藏! 实现效果 需求分析 默认
    的头像 发表于 06-09 15:51 490次阅读
    HarmonyOS实战:<b class='flag-5'>自定义</b>时间选择器

    HarmonyOS应用自定义键盘解决方案

    自定义键盘是一种替换系统默认键盘的解决方案,可实现键盘个性化交互。允许用户结合业务需求与操作习惯,对按键布局进行可视化重构、设置多功能组合键位,使输入更加便捷和舒适。在安全防护层面,自定义
    的头像 发表于 06-05 14:19 1581次阅读

    如何使用自定义设置回调函数?

    你好,我正在尝试编写自己的自定义设置回调函数,并使用 fastEnum=false。 是否有任何代码示例或资料可供我参考? void CyU3PUsbRegisterSetupCallback
    发表于 05-21 06:11

    LabVIEW运动控制(三):EtherCAT运动控制器的高效加工指令自定义封装

    LabVIEW高效加工指令自定义封装
    的头像 发表于 04-08 13:49 3267次阅读
    LabVIEW运动控制(三):EtherCAT运动控制器的高效加工指令<b class='flag-5'>自定义</b>封装

    如何添加自定义单板

    在开发过程中,用户有时需要创建自定义板配置。本节将通过一个实例讲解用户如何创建属于自己的machine,下面以g2l-test.conf为例进行说明。
    的头像 发表于 03-12 14:43 1082次阅读

    如何快速创建用户自定义Board和App工程

    概述自HPM_SDKv1.7.0发布开始,在HPM_ENV中新增了user_template文件夹,以方便用户快速创建自定义的Board和App工程。user_template是用户模板工程,用户
    的头像 发表于 02-08 13:38 1001次阅读
    如何快速创建用户<b class='flag-5'>自定义</b>Board和App工程

    CAN总线十万个为什么 | CAN自定义波特率有什么用?

    波特率一致即可顺利进行。然而,也存在一些特殊情况。例如,即使确认了CAN总线的波特率,通信仍无法正常建立,但通过设置自定义波特率,问题却得以解决。这究竟是为什么呢
    的头像 发表于 02-07 11:36 1100次阅读
    CAN总线十万个为什么 | CAN<b class='flag-5'>自定义</b>波特率有什么用?

    Altium Designer 15.0自定义元件设计

    电子发烧友网站提供《Altium Designer 15.0自定义元件设计.pdf》资料免费下载
    发表于 01-21 15:04 0次下载
    Altium Designer 15.0<b class='flag-5'>自定义</b>元件设计

    think-cell:自定义think-cell(四)

    C.5 设置默认议程幻灯片布局 think-cell 议程可以在演示文稿中使用特定的自定义布局来定义议程、位置和议程幻灯片上的其他形状,例如标题或图片。通过将此自定义布局添加到模板,您
    的头像 发表于 01-13 10:37 881次阅读
    think-cell:<b class='flag-5'>自定义</b>think-cell(四)

    智能语音识别照明解决方案,平台自定义,中英切换

    智能语音识别照明方案引入NRK3502芯片,支持平台自定义,离线控制,中英双语切换。NRK3502具备高性能和灵活自定义能力,可推动智能照明革新,控制其他智能设备,为国际用户提供全方位智能生活体验。
    的头像 发表于 01-10 13:23 801次阅读
    智能语音识别照明解决方案,平台<b class='flag-5'>自定义</b>,中英切换

    think-cell;自定义think-cell(一)

    本章介绍如何自定义 think-cell,即如何更改默认颜色和其他默认属性;这是通过 think-cell 的样式文件完成的,这些文件将在前四个部分中进行讨论。 第五部分 C.5 设置默认议程幻灯片
    的头像 发表于 01-08 11:31 1243次阅读
    think-cell;<b class='flag-5'>自定义</b>think-cell(一)

    think-cell:自定义think-cell(二)

    于当前演示文稿中的任何新图表。 例如,从 think-cell 安装目录中的目录加载示例样式文件后,颜色和配色方案属性控件将包含自定义项。example_style_complex.xmlstyles
    的头像 发表于 01-08 09:40 678次阅读
    think-cell:<b class='flag-5'>自定义</b>think-cell(二)