本项目是基于开源项目AZExplosion进行鸿蒙化的移植和开发的,可以通过项目标签以及github地址( https://github.com/Xieyupeng520/AZExplosion )追踪到原安卓项目版本。
项目名称:Azexplosion_ohos
所属系列:鸿蒙的第三方组件适配移植
功能:实现了点击图片粒子破碎效果,以及动画的各种属性用法。
调用差异:无
开发环境:sdk5,DevEco Studio2.1 beta3
项目发起作者:胡鹏达
原项目Doc地址:https://github.com/Xieyupeng520/AZExplosion
编程语言:Java
安装教程 下载AZExplosion的har包explosopn.har(位于output文件夹下)。
启动 DevEco Studio,将下载的har包,导入工程目录“entry->libs”下。
在moudle级别下的build.gradle文件中添加依赖,在dependences标签中增加对libs目录下jar包的引用。
dependencies { implementation fileTree(dir: 'libs', include: ['.jar', '.har']) …… } 在导入的har包上点击右键,选择“Add as Library”对包进行引用,选择需要引用的模块,并点击“OK”即引用成功。 在sdk5,DevEco Studio2.1 beta3下项目可直接运行
1.需要用到的主要资源
1.1 新建对象
public class Particle {
//默认小球宽高
public static final int PART_WH = 5;
//粒子圆心x
float cx;
//粒子圆心y
float cy;
//粒子半径
float radius;
//颜色
int color;
//透明度
float alpha;
Rect mBound;
1.2新建ExplosionField对象,继承自Component,用于做粒子集的画布,需要重写onDraw()方法
public class ExplosionField extends Component {
private static final String TAG = "ExplosionField";
public final float DENSITY = DisplayManager.getInstance().getDefaultDisplay(getContext()).get().getAttributes().densityPixels;
public int dp2px(int dp) {
return Math.round(dp * DENSITY);
}
//定义canvas
private static final Canvas mCanvas = new Canvas();
//用一个List保存动画集
private ArrayList<ExplosionAnimator> explosionAnimators;
private ClickedListener onClickListener;
private boolean endFlag = true;
public ExplosionField(Context context) {
super(context);
init();
}
public ExplosionField(Context context, AttrSet attrs) {
super(context, attrs);
init();
}
//初始化
private void init() {
explosionAnimators = new ArrayList<ExplosionAnimator>();
attach2Activity((Ability) getContext());
}
1.3新建ExplosionAnimator,继承自ValueAnimator,用来执行自定义动画。
public class ExplosionAnimator extends AnimatorValue implements AnimatorValue.ValueUpdateListener {
//默认时间间隔
public static final int DEFAULT_DURATION = 1500;
//粒子
private Particle[][] mParticles;
//画笔
private Paint mPaint;
//组件
private Component mContainer;
private float myvalue =0;
//粒子动画
public ExplosionAnimator(Component view, PixelMap bitmap, Rect bound) {
mPaint = new Paint();
mContainer = view;
//设置默认时间
setDuration(DEFAULT_DURATION);
setValueUpdateListener(this);
//粒子调用generateParticles方法
mParticles = generateParticles(bitmap, bound);
}
1.4先通过view的宽高创建出一个同样大小的空白图,用PixelMap 的静态方法createPixelmap()创建
private PixelMap getPixelMap(int resId) {
InputStream drawableInputStream = null;
try {
drawableInputStream = getResourceManager().getResource(resId);
ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
sourceOptions.formatHint = "image/png";
ImageSource imageSource = ImageSource.create(drawableInputStream, null);
ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
//设置格式
decodingOptions.desiredPixelFormat = PixelFormat.ARGB_8888;
PixelMap pixelMap = imageSource.createPixelmap(decodingOptions);
return pixelMap;
} catch (Exception e) {
e.printStackTrace();
} finally {
try{
if (drawableInputStream != null){
drawableInputStream.close();
}
}catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
1.5把快照分解成若干个粒子,这些粒子的组合能看出来是原图的影子,然后再让粒子动起来形成后面的动画,在Particle类中定义静态方法generateParticle()用来生成新的Particle对象
public static Particle generateParticle(int color, Rect bound, Point point) {
//行是高
int row = point.getPointYToInt();
//列是宽
int column = point.getPointXToInt();
//新建粒子
Particle particle = new Particle();
particle.mBound = bound;
//粒子颜色
particle.color = color;
//粒子透明度
particle.alpha = 1f;
//把半径设为宽长
particle.radius = PART_WH;
// 圆心坐标
particle.cx = bound.left+ PART_WH * column;
particle.cy = bound.top + PART_WH * row;
return particle;
}
1.6在ExplosionAnimator中通过方法getAnimatedValue()就能够不断得到递增的范围(记做factor)。我们先在Particle写好得到变化因素后,属性要发生的改变。cx左右移动都可以,cy向下移动且距离和view高度有关,radius变小,alpha变得越来越透明。public void advance(float factor) {
//移动粒子x坐标
cx = cx + factor * random.nextInt(mBound.getWidth()) * (random.nextFloat() -0.5f);
//移动粒子y坐标
cy = cy + factor * random.nextInt(mBound.getHeight() / 2);
//半径变小
radius = radius - factor * random.nextInt(2);
//透明度也逐渐改变
alpha = (1f - factor) * (1 + random.nextFloat());
}
}
1.7在ExplosionField中建立一个“爆炸”方法,只要调用这个方法,传入Component,最后执行animator.start(),Component,就会执行爆炸效果。
public void explode(final Component view) {
//获取view在屏幕上的绝对坐标
int[] positions = view.getLocationOnScreen();
//修正因为状态栏导致的错位
positions[1] = positions[1] - 159;
Rect rect = view.getComponentPosition();
//使得图片与破碎大小一致
rect.set(rect.left-75,rect.top,rect.right+75,rect.bottom+150);
final ExplosionAnimator animator = new ExplosionAnimator(this, createBitmapFromView(view), rect);
explosionAnimators.add(animator);
1.8在Activity的最上层盖一层透明的ExplosionField视图,用来显示粒子动画。
private void attach2Activity(Ability activity) {
ComponentContainer rootView = (ComponentContainer) activity.findComponentById(ResourceTable.Id_group1).getComponentParent ().getComponentParent();
ComponentContainer.LayoutConfig lp = new ComponentContainer.LayoutConfig(
ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT);
rootView.addComponent(this, lp);
}
1.9调用了addListener()方法,就是把需要实现点击破碎效果的view加上监听器
public void addListener(Component view) {
if (view instanceof ComponentContainer) {
ComponentContainer viewGroup = (ComponentContainer) view;
int count = viewGroup.getChildCount();
for (int i = 0 ; i < count; i++) {
addListener(viewGroup.getComponentAt(i));
}
} else {
view.setClickable(true);
view.setClickedListener(getOnClickListener());
}
}
private ClickedListener getOnClickListener() {
if (null == onClickListener) {
onClickListener = new ClickedListener() {
@Override
public void onClick(Component component) {
ExplosionField.this.explode(component);
}
};
}
return onClickListener;
}
}
2.布局及初始化
2.1xml布局
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:id="$+id:root"
ohos:width="match_parent"
ohos:height="match_parent"
ohos:orientation="vertical"
>
<Text
ohos:width="match_content"
ohos:text="破碎效果"
ohos:text_size="60vp"
ohos:top_margin="10vp"
ohos:left_margin="30vp"
ohos:bottom_margin="15vp"
ohos:right_padding="15vp"
ohos:left_padding="15vp"
ohos:height="match_content"/>
<DirectionalLayout ohos:id="$+id:group1"
ohos:width="match_parent"
ohos:height="100vp"
ohos:top_margin="10vp"
ohos:orientation="horizontal"
>
<Image
ohos:id="$+id:qq"
ohos:width="match_content"
ohos:height="match_content"
ohos:image_src="$media:qq"
ohos:left_margin="25vp"
ohos:right_margin="25vp"
ohos:top_margin="15vp"
/>
<Image
ohos:id="$+id:qzone"
ohos:width="match_content"
ohos:height="match_content"
ohos:image_src="$media:qzone"
ohos:left_margin="25vp"
ohos:right_margin="25vp"
ohos:top_margin="15vp"
/>
<Image
ohos:id="$+id:vx"
ohos:width="match_content"
ohos:height="match_content"
ohos:image_src="$media:vx"
ohos:left_margin="25vp"
ohos:right_margin="25vp"
ohos:top_margin="15vp"
/>
<Image
ohos:id="$+id:qq_music"
ohos:width="match_content"
ohos:height="match_content"
ohos:image_src="$media:qq_music"
ohos:left_margin="25vp"
ohos:top_margin="15vp"
ohos:right_margin="25vp"
/>
</DirectionalLayout>
<DirectionalLayout
ohos:width="match_parent"
ohos:height="100vp"
ohos:top_margin="10vp"
ohos:orientation="horizontal">
<Image
ohos:id="$+id:wb"
ohos:width="match_content"
ohos:height="match_content"
ohos:image_src="$media:wb"
ohos:left_margin="25vp"
ohos:right_margin="25vp"
ohos:top_margin="15vp"
/>
<Image
ohos:id="$+id:tb"
ohos:width="match_content"
ohos:height="match_content"
ohos:image_src="$media:tb"
ohos:left_margin="25vp"
ohos:right_margin="25vp"
ohos:top_margin="15vp"
/>
<Image
ohos:id="$+id:gaode_map"
ohos:width="match_content"
ohos:height="match_content"
ohos:image_src="$media:gaode_map"
ohos:left_margin="25vp"
ohos:right_margin="25vp"
ohos:top_margin="15vp"
/>
<Image
ohos:id="$+id:baidu_map"
ohos:width="match_content"
ohos:height="match_content"
ohos:image_src="$media:baidu_map"
ohos:left_margin="25vp"
ohos:right_margin="25vp"
ohos:top_margin="15vp"
/>
</DirectionalLayout>
<DirectionalLayout
ohos:width="match_parent"
ohos:height="100vp"
ohos:top_margin="10vp"
ohos:orientation="horizontal">
<Image
ohos:id="$+id:iqiyi"
ohos:width="match_content"
ohos:height="match_content"
ohos:image_src="$media:iqiyi"
ohos:left_margin="25vp"
ohos:right_margin="25vp"
ohos:top_margin="15vp"
/>
<Image
ohos:id="$+id:changba"
ohos:width="match_content"
ohos:height="match_content"
ohos:image_src="$media:changba"
ohos:left_margin="25vp"
ohos:right_margin="25vp"
ohos:top_margin="15vp"
/>
<Image
ohos:id="$+id:jd"
ohos:width="match_content"
ohos:height="match_content"
ohos:image_src="$media:jd"
ohos:left_margin="25vp"
ohos:right_margin="25vp"
ohos:top_margin="15vp"
/>
</DirectionalLayout>
</DirectionalLayout>
2.2 代码中使用布局并初始化
private PixelMap createBitmapFromView(Component view) {
PixelMap.InitializationOptions options = new PixelMap.InitializationOptions();
options.size = new Size(100,100);
PixelMap bitmap = PixelMap.create(options);
if(view.getName().equals("Id_qq")){
bitmap =getPixelMap(ResourceTable.Media_qq);
}
if(view.getName().equals("Id_qzone"))
bitmap =getPixelMap(ResourceTable.Media_qzone);
if(view.getName().equals("Id_vx"))
bitmap =getPixelMap(ResourceTable.Media_vx);
if(view.getName().equals("Id_wb"))
bitmap =getPixelMap(ResourceTable.Media_wb);
if(view.getName().equals("Id_tb"))
bitmap =getPixelMap(ResourceTable.Media_tb);
if(view.getName().equals("Id_baidu_map"))
bitmap =getPixelMap(ResourceTable.Media_baidu_map);
if(view.getName().equals("Id_gaode_map"))
bitmap =getPixelMap(ResourceTable.Media_gaode_map);
if(view.getName().equals("Id_qq_music"))
bitmap =getPixelMap(ResourceTable.Media_qq_music);
return bitmap;
}
版本迭代
v0.1.0-alpha
版权和许可信息
azexplosion_ohos经过[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0)授权许可.
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
1. 开源生态
2. 协作、人、软件
3. 评估模型