Android原生实现控件outline方案(API28及以上)

Android控件的Outline效果的实现方式有很多种,这里介绍一下另一种使用Canvas.drawPath()方法来绘制控件轮廓Path路径的实现方案(API28及以上)。

实现效果:
在这里插入图片描述

属性

添加Outline相关属性,主要包括颜色和Stroke宽度:

<declare-styleable name="shape_button">...<attr name="carbon_stroke" /><attr name="carbon_strokeWidth" />
</declare-styleable>

StrokeView接口

创建一个StrokeView通用接口:

/*** 外部轮廓相关*/
public interface StrokeView {ColorStateList getStroke();void setStroke(ColorStateList color);void setStroke(int color);float getStrokeWidth();void setStrokeWidth(float strokeWidth);
}

ShapeButton 实现这个StrokeView接口:

public class ShapeButton extends AppCompatButtonimplements ShadowView,ShapeModelView,RippleView,StrokeView {public ShapeButton(@NonNull Context context) {super(context);initButton(null, android.R.attr.buttonStyle, R.style.carbon_Button);}public ShapeButton(@NonNull Context context, @Nullable AttributeSet attrs) {super(context, attrs);initButton(attrs, android.R.attr.buttonStyle, R.style.carbon_Button);}public ShapeButton(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initButton(attrs, defStyleAttr, R.style.carbon_Button);}public ShapeButton(Context context, String text, OnClickListener listener) {super(context);initButton(null, android.R.attr.buttonStyle, R.style.carbon_Button);setText(text);setOnClickListener(listener);}private static int[] elevationIds = new int[]{R.styleable.shape_button_carbon_elevation,R.styleable.shape_button_carbon_elevationShadowColor,R.styleable.shape_button_carbon_elevationAmbientShadowColor,R.styleable.shape_button_carbon_elevationSpotShadowColor};private static int[] cornerCutRadiusIds = new int[]{R.styleable.shape_button_carbon_cornerRadiusTopStart,R.styleable.shape_button_carbon_cornerRadiusTopEnd,R.styleable.shape_button_carbon_cornerRadiusBottomStart,R.styleable.shape_button_carbon_cornerRadiusBottomEnd,R.styleable.shape_button_carbon_cornerRadius,R.styleable.shape_button_carbon_cornerCutTopStart,R.styleable.shape_button_carbon_cornerCutTopEnd,R.styleable.shape_button_carbon_cornerCutBottomStart,R.styleable.shape_button_carbon_cornerCutBottomEnd,R.styleable.shape_button_carbon_cornerCut};private static int[] rippleIds = new int[]{R.styleable.shape_button_carbon_rippleColor,R.styleable.shape_button_carbon_rippleStyle,R.styleable.shape_button_carbon_rippleHotspot,R.styleable.shape_button_carbon_rippleRadius};private static int[] strokeIds = new int[]{R.styleable.shape_button_carbon_stroke,R.styleable.shape_button_carbon_strokeWidth};protected TextPaint paint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);private void initButton(AttributeSet attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.shape_button, defStyleAttr, defStyleRes);Carbon.initElevation(this, a, elevationIds);Carbon.initCornerCutRadius(this,a,cornerCutRadiusIds);Carbon.initRippleDrawable(this,a,rippleIds);// 初始化Stroke相关属性Carbon.initStroke(this,a,strokeIds);a.recycle();}// -------------------------------// shadow// -------------------------------// -------------------------------// shape// -------------------------------// -------------------------------// ripple// -------------------------------// -------------------------------// stroke// -------------------------------private ColorStateList stroke;private float strokeWidth;private Paint strokePaint;// 绘制轮廓private void drawStroke(Canvas canvas) {strokePaint.setStrokeWidth(strokeWidth * 2);strokePaint.setColor(stroke.getColorForState(getDrawableState(), stroke.getDefaultColor()));// cornersMask这是之前装载控件轮廓的path对象cornersMask.setFillType(Path.FillType.WINDING);canvas.drawPath(cornersMask, strokePaint);}// 设置轮廓颜色@Overridepublic void setStroke(ColorStateList colorStateList) {stroke = colorStateList;if (stroke == null)return;if (strokePaint == null) {strokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);strokePaint.setStyle(Paint.Style.STROKE);}}// 设置轮廓颜色@Overridepublic void setStroke(int color) {setStroke(ColorStateList.valueOf(color));}@Overridepublic ColorStateList getStroke() {return stroke;}// 设置轮廓线条宽度@Overridepublic void setStrokeWidth(float strokeWidth) {this.strokeWidth = strokeWidth;}@Overridepublic float getStrokeWidth() {return strokeWidth;}}

初始化Stroke属性

    public static void initStroke(StrokeView strokeView, TypedArray a, int[] ids) {int carbon_stroke = ids[0];int carbon_strokeWidth = ids[1];View view = (View) strokeView;ColorStateList color =  a.getColorStateList(carbon_stroke);if (color != null)strokeView.setStroke(color);strokeView.setStrokeWidth(a.getDimension(carbon_strokeWidth, 0));}

绘制轮廓

onDraw()方法的super.draw(canvas);后面执行drawStroke()方法:

public void drawInternal(@NonNull Canvas canvas) {super.draw(canvas);if(stroke!=null){drawStroke(canvas);}}

如何使用

<com.chinatsp.demo1.shadow.ShapeButtonandroid:id="@+id/show_dialog_btn"android:layout_width="wrap_content"android:layout_height="36dp"android:layout_margin="@dimen/carbon_padding"android:background="#ffffff"android:stateListAnimator="@null"android:text="TOM"app:carbon_cornerCut="4dp"app:carbon_elevation="30dp"app:carbon_elevationShadowColor="#40ff0000"app:carbon_rippleColor="#40ff0000"app:carbon_rippleStyle="borderless"app:carbon_rippleRadius="30dp"app:carbon_stroke="@color/carbon_green_400"app:carbon_strokeWidth="1dp"/>

完整代码:

public class ShapeButton extends AppCompatButtonimplements ShadowView,ShapeModelView,RippleView,StrokeView {public ShapeButton(@NonNull Context context) {super(context);initButton(null, android.R.attr.buttonStyle, R.style.carbon_Button);}public ShapeButton(@NonNull Context context, @Nullable AttributeSet attrs) {super(context, attrs);initButton(attrs, android.R.attr.buttonStyle, R.style.carbon_Button);}public ShapeButton(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initButton(attrs, defStyleAttr, R.style.carbon_Button);}public ShapeButton(Context context, String text, OnClickListener listener) {super(context);initButton(null, android.R.attr.buttonStyle, R.style.carbon_Button);setText(text);setOnClickListener(listener);}private static int[] elevationIds = new int[]{R.styleable.shape_button_carbon_elevation,R.styleable.shape_button_carbon_elevationShadowColor,R.styleable.shape_button_carbon_elevationAmbientShadowColor,R.styleable.shape_button_carbon_elevationSpotShadowColor};private static int[] cornerCutRadiusIds = new int[]{R.styleable.shape_button_carbon_cornerRadiusTopStart,R.styleable.shape_button_carbon_cornerRadiusTopEnd,R.styleable.shape_button_carbon_cornerRadiusBottomStart,R.styleable.shape_button_carbon_cornerRadiusBottomEnd,R.styleable.shape_button_carbon_cornerRadius,R.styleable.shape_button_carbon_cornerCutTopStart,R.styleable.shape_button_carbon_cornerCutTopEnd,R.styleable.shape_button_carbon_cornerCutBottomStart,R.styleable.shape_button_carbon_cornerCutBottomEnd,R.styleable.shape_button_carbon_cornerCut};private static int[] rippleIds = new int[]{R.styleable.shape_button_carbon_rippleColor,R.styleable.shape_button_carbon_rippleStyle,R.styleable.shape_button_carbon_rippleHotspot,R.styleable.shape_button_carbon_rippleRadius};private static int[] strokeIds = new int[]{R.styleable.shape_button_carbon_stroke,R.styleable.shape_button_carbon_strokeWidth};protected TextPaint paint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);private void initButton(AttributeSet attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.shape_button, defStyleAttr, defStyleRes);Carbon.initElevation(this, a, elevationIds);Carbon.initCornerCutRadius(this,a,cornerCutRadiusIds);Carbon.initRippleDrawable(this,a,rippleIds);Carbon.initStroke(this,a,strokeIds);a.recycle();}// -------------------------------// shadow// -------------------------------private float elevation = 0;private float translationZ = 0;private ColorStateList ambientShadowColor, spotShadowColor;@Overridepublic float getElevation() {return elevation;}@Overridepublic void setElevation(float elevation) {if (Carbon.IS_PIE_OR_HIGHER) {super.setElevation(elevation);super.setTranslationZ(translationZ);} else if (Carbon.IS_LOLLIPOP_OR_HIGHER) {if (ambientShadowColor == null || spotShadowColor == null) {super.setElevation(elevation);super.setTranslationZ(translationZ);} else {super.setElevation(0);super.setTranslationZ(0);}} else if (elevation != this.elevation && getParent() != null) {((View) getParent()).postInvalidate();}this.elevation = elevation;}@Overridepublic float getTranslationZ() {return translationZ;}public void setTranslationZ(float translationZ) {if (translationZ == this.translationZ)return;if (Carbon.IS_PIE_OR_HIGHER) {super.setTranslationZ(translationZ);} else if (Carbon.IS_LOLLIPOP_OR_HIGHER) {if (ambientShadowColor == null || spotShadowColor == null) {super.setTranslationZ(translationZ);} else {super.setTranslationZ(0);}} else if (translationZ != this.translationZ && getParent() != null) {((View) getParent()).postInvalidate();}this.translationZ = translationZ;}@Overridepublic ColorStateList getElevationShadowColor() {return ambientShadowColor;}@Overridepublic void setElevationShadowColor(ColorStateList shadowColor) {ambientShadowColor = spotShadowColor = shadowColor;setElevation(elevation);setTranslationZ(translationZ);}@Overridepublic void setElevationShadowColor(int color) {ambientShadowColor = spotShadowColor = ColorStateList.valueOf(color);setElevation(elevation);setTranslationZ(translationZ);}@Overridepublic void setOutlineAmbientShadowColor(ColorStateList color) {ambientShadowColor = color;if (Carbon.IS_PIE_OR_HIGHER) {super.setOutlineAmbientShadowColor(color.getColorForState(getDrawableState(), color.getDefaultColor()));} else {setElevation(elevation);setTranslationZ(translationZ);}}@Overridepublic void setOutlineAmbientShadowColor(int color) {setOutlineAmbientShadowColor(ColorStateList.valueOf(color));}@Overridepublic int getOutlineAmbientShadowColor() {return ambientShadowColor.getDefaultColor();}@Overridepublic void setOutlineSpotShadowColor(int color) {setOutlineSpotShadowColor(ColorStateList.valueOf(color));}@Overridepublic void setOutlineSpotShadowColor(ColorStateList color) {spotShadowColor = color;if (Carbon.IS_PIE_OR_HIGHER) {super.setOutlineSpotShadowColor(color.getColorForState(getDrawableState(), color.getDefaultColor()));} else {setElevation(elevation);setTranslationZ(translationZ);}}@Overridepublic int getOutlineSpotShadowColor() {return ambientShadowColor.getDefaultColor();}@Overridepublic boolean hasShadow() {return false;}@Overridepublic void drawShadow(Canvas canvas) {}@Overridepublic void draw(Canvas canvas) {boolean c = !Carbon.isShapeRect(shapeModel, boundsRect);if (Carbon.IS_PIE_OR_HIGHER) {if (spotShadowColor != null)super.setOutlineSpotShadowColor(spotShadowColor.getColorForState(getDrawableState(), spotShadowColor.getDefaultColor()));if (ambientShadowColor != null)super.setOutlineAmbientShadowColor(ambientShadowColor.getColorForState(getDrawableState(), ambientShadowColor.getDefaultColor()));}// 判断如果不是圆角矩形,需要使用轮廓Path,绘制一下Path,不然显示会很奇怪if (getWidth() > 0 && getHeight() > 0 && ((c && !Carbon.IS_LOLLIPOP_OR_HIGHER) || !shapeModel.isRoundRect(boundsRect))) {int saveCount = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);drawInternal(canvas);paint.setXfermode(Carbon.CLEAR_MODE);if (c) {cornersMask.setFillType(Path.FillType.INVERSE_WINDING);canvas.drawPath(cornersMask, paint);}canvas.restoreToCount(saveCount);paint.setXfermode(null);}else{drawInternal(canvas);}}public void drawInternal(@NonNull Canvas canvas) {super.draw(canvas);if(stroke!=null){drawStroke(canvas);}if (rippleDrawable != null && rippleDrawable.getStyle() == RippleDrawable.Style.Over)rippleDrawable.draw(canvas);}// -------------------------------// shape// -------------------------------private ShapeAppearanceModel shapeModel = new ShapeAppearanceModel();private MaterialShapeDrawable shadowDrawable = new MaterialShapeDrawable(shapeModel);@Overridepublic void setShapeModel(ShapeAppearanceModel shapeModel) {this.shapeModel = shapeModel;shadowDrawable = new MaterialShapeDrawable(shapeModel);if (getWidth() > 0 && getHeight() > 0)updateCorners();if (!Carbon.IS_LOLLIPOP_OR_HIGHER)postInvalidate();}// View的轮廓形状private RectF boundsRect = new RectF();// View的轮廓形状形成的Path路径private Path cornersMask = new Path();/*** 更新圆角*/private void updateCorners() {if (Carbon.IS_LOLLIPOP_OR_HIGHER) {// 如果不是矩形,裁剪View的轮廓if (!Carbon.isShapeRect(shapeModel, boundsRect)){setClipToOutline(true);}//该方法返回一个Outline对象,它描述了该视图的形状。setOutlineProvider(new ViewOutlineProvider() {@Overridepublic void getOutline(View view, Outline outline) {if (Carbon.isShapeRect(shapeModel, boundsRect)) {outline.setRect(0, 0, getWidth(), getHeight());} else {shadowDrawable.setBounds(0, 0, getWidth(), getHeight());shadowDrawable.setShadowCompatibilityMode(MaterialShapeDrawable.SHADOW_COMPAT_MODE_NEVER);shadowDrawable.getOutline(outline);}}});}// 拿到圆角矩形的形状boundsRect.set(shadowDrawable.getBounds());// 拿到圆角矩形的PathshadowDrawable.getPathForSize(getWidth(), getHeight(), cornersMask);}@Overridepublic ShapeAppearanceModel getShapeModel() {return this.shapeModel;}@Overridepublic void setCornerCut(float cornerCut) {shapeModel = ShapeAppearanceModel.builder().setAllCorners(new CutCornerTreatment(cornerCut)).build();setShapeModel(shapeModel);}@Overridepublic void setCornerRadius(float cornerRadius) {shapeModel = ShapeAppearanceModel.builder().setAllCorners(new RoundedCornerTreatment(cornerRadius)).build();setShapeModel(shapeModel);}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);if (!changed)return;if (getWidth() == 0 || getHeight() == 0)return;updateCorners();if (rippleDrawable != null)rippleDrawable.setBounds(0, 0, getWidth(), getHeight());}// -------------------------------// ripple// -------------------------------private RippleDrawable rippleDrawable;@Overridepublic boolean dispatchTouchEvent(@NonNull MotionEvent event) {if (rippleDrawable != null && event.getAction() == MotionEvent.ACTION_DOWN)rippleDrawable.setHotspot(event.getX(),event.getY());return super.dispatchTouchEvent(event);}@Overridepublic RippleDrawable getRippleDrawable() {return rippleDrawable;}@Overridepublic void setRippleDrawable(RippleDrawable newRipple) {if (rippleDrawable != null) {rippleDrawable.setCallback(null);if (rippleDrawable.getStyle() == RippleDrawable.Style.Background)super.setBackgroundDrawable(rippleDrawable.getBackground());}if (newRipple != null) {newRipple.setCallback(this);newRipple.setBounds(0, 0, getWidth(), getHeight());newRipple.setState(getDrawableState());((Drawable) newRipple).setVisible(getVisibility() == VISIBLE, false);if (newRipple.getStyle() == RippleDrawable.Style.Background)super.setBackgroundDrawable((Drawable) newRipple);}rippleDrawable = newRipple;}@Overrideprotected void drawableStateChanged() {super.drawableStateChanged();if (rippleDrawable != null && rippleDrawable.getStyle() != RippleDrawable.Style.Background)rippleDrawable.setState(getDrawableState());}@Overrideprotected boolean verifyDrawable(@NonNull Drawable who) {return super.verifyDrawable(who) || rippleDrawable == who;}@Overridepublic void invalidateDrawable(@NonNull Drawable drawable) {super.invalidateDrawable(drawable);invalidateParentIfNeeded();}@Overridepublic void invalidate(@NonNull Rect dirty) {super.invalidate(dirty);invalidateParentIfNeeded();}@Overridepublic void invalidate(int l, int t, int r, int b) {super.invalidate(l, t, r, b);invalidateParentIfNeeded();}@Overridepublic void invalidate() {super.invalidate();invalidateParentIfNeeded();}private void invalidateParentIfNeeded() {if (getParent() == null || !(getParent() instanceof View))return;if (rippleDrawable != null && rippleDrawable.getStyle() == RippleDrawable.Style.Borderless)((View) getParent()).invalidate();}@Overridepublic void setBackground(Drawable background) {setBackgroundDrawable(background);}@Overridepublic void setBackgroundDrawable(Drawable background) {if (background instanceof RippleDrawable) {setRippleDrawable((RippleDrawable) background);return;}if (rippleDrawable != null && rippleDrawable.getStyle() == RippleDrawable.Style.Background) {rippleDrawable.setCallback(null);rippleDrawable = null;}super.setBackgroundDrawable(background);}// -------------------------------// stroke// -------------------------------private ColorStateList stroke;private float strokeWidth;private Paint strokePaint;private void drawStroke(Canvas canvas) {strokePaint.setStrokeWidth(strokeWidth * 2);strokePaint.setColor(stroke.getColorForState(getDrawableState(), stroke.getDefaultColor()));cornersMask.setFillType(Path.FillType.WINDING);canvas.drawPath(cornersMask, strokePaint);}@Overridepublic void setStroke(ColorStateList colorStateList) {stroke = colorStateList;if (stroke == null)return;if (strokePaint == null) {strokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);strokePaint.setStyle(Paint.Style.STROKE);}}@Overridepublic void setStroke(int color) {setStroke(ColorStateList.valueOf(color));}@Overridepublic ColorStateList getStroke() {return stroke;}@Overridepublic void setStrokeWidth(float strokeWidth) {this.strokeWidth = strokeWidth;}@Overridepublic float getStrokeWidth() {return strokeWidth;}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/128878.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RunnerGo亮相QECon大会上海站,来看看这款全栈测试平台

QECon&#xff08;Quality Efficiency Conference&#xff09;质量效能大会在上海正式开幕&#xff01;本次大会以"数生智慧&#xff1a;高质量发展新引擎"为主题&#xff0c;深入探讨如何借助数字化和智能化技术推动软件质量的发展&#xff0c;为高质量经济发展提供…

ctfshow web入门 php特性 web126-web130

1.web126 和前面一样的 payload&#xff1a; get: a1fl0gflag_give_me post: CTF_SHOW&CTF[SHOW.COM&funparse_str($a[1]) 或 get: ?$fl0gflag_give_me post:CTF_SHOW&CTF[SHOW.COM&funassert($a[0]) assert($a[0]) 是把fl0g赋值为flag_give_me $a[0]是当前…

运营商大数据,三网融合大数据,联通大数据,移动大数据

有许多公司和企业依靠电话营销和短信营销。对于他们来说&#xff0c;客户资源就是维生素和维生素&#xff0c;客户资源的及时性和准确性是这些公司和企业最关心的问题。长期使用低质量、大量无效的客户资源&#xff0c;是对时间的浪费&#xff0c;是对人力物力财力的浪费&#…

opengauss数据备份(docker中备份)

首先如果想直接在宿主机上进行使用gs_dump备份需要glibc的版本到2.34及以上&#xff0c;查看版本命令为 ldd --version 如图所示&#xff0c;本宿主机并不满足要求&#xff0c;所以转向在docker容器中进行备份&#xff0c; 然后进入opengauss容器中&#xff0c;命令为 docker…

华为数通方向HCIP-DataCom H12-831题库(单选题:221-240)

第221题 以下哪些项能被正则表达式^30.成功匹配? A、200 100 300 B、100 200 300 C、300 200 100 D、300 100 200 答案:CD 解析: 30.其中的“点”表示的是任何的一个数字,表示的是as-path的开头;所以以300开头的都是满足题目需求的。 第222题 以下哪些项的Community属性能…

使用kubectl连接远程Kubernetes(k8s)集群

使用kubectl连接远程Kubernetes集群 环境准备下载kubectl下载地址 安装kubectl并处理配置文件Windows的安装配置安装kubectl拉取配置文件安装kubectl拉取配置文件kubectl命令自动补全 Linux的安装配置安装kubectl拉取配置文件kubectl命令自动补全 环境准备 你需要准备一个Kube…

ElasticSearch 学习7 集成ik分词器

网上找了一大堆&#xff0c;很多都介绍的不详细&#xff0c;开始安装完一直报错找不到plugin-descriptor.properties&#xff0c;有些懵这个东西不应该带在里面吗&#xff0c;参考了一篇博客说新建一个这个&#xff0c;新建完可以启动&#xff0c;但是插入索引数据会报错找不到…

Linux虚拟机搭建RabbitMQ集群

普通集群模式&#xff0c;意思就是在多台机器上启动多个 RabbitMQ 实例&#xff0c;每台机器启动一个。创建的 queue&#xff0c;只会放在一个 RabbitMQ 实例上&#xff0c;但是每个实例都同步 queue 的元数据&#xff08;元数据可以认为是 queue 的一些配置信息&#xff0c;通…

华为OD机试 - 最优策略组合下的总的系统消耗资源数(Java 2023 B卷 100分)

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明4、思路 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷…

数学建模预测模型MATLAB代码大合集及皮尔逊相关性分析(无需调试、开源)

已知2010-2020数据&#xff0c;预测2021-2060数据 一、Logistic预测人口 %%logistic预测2021-2060年结果 clear;clc; X[7869.34, 8022.99, 8119.81, 8192.44, 8281.09, 8315.11, 8381.47, 8423.50, 8446.19, 8469.09, 8477.26]; nlength(X)-1; for t1:nZ(t)(X(t1)-X(t))/X(t1…

【物联网】Arduino+ESP8266物联网开发(一):开发环境搭建 安装Arduino和驱动

ESP8266物联网开发 1.开发环境安装 开发软件下载地址&#xff1a; 链接: https://pan.baidu.com/s/1BaOY7kWTvh4Obobj64OHyA?pwd3qv8 提取码: 3qv8 1.1 安装驱动 将ESP8266连接到电脑上&#xff0c;安装ESP8266驱动CP210x 安装成功后&#xff0c;打开设备管理器&#xff0c…

C语言数据结构 1.1 初学数据结构

数据结构的基本概念 数据结构在学什么&#xff1f; 如何用程序代码把现实世界的问题信息化 如何用计算机高效处理信息从而创造价值 数据&#xff1a; 数据元素、数据项&#xff1a; 数据元素——描述一个个体 数据对象——数据元素之间具有同样的性质 同一个数据对象里的数…