评论

收藏

[Android] 如何用程序员的方式,营造七夕氛围感?

移动开发 移动开发 发布于:2021-08-14 13:13 | 阅读数:279 | 评论:0

一个“冷”知识,又双叒叕到一年七夕了!
每年此时,送礼指南满天飞,选择困难症都给逼出来了,疑了个惑,能搞定爱情的人,却在送礼这件事儿上纠结万分!
要我说,七夕这种有情人的浪漫佳节,最重要的是图一个氛围!今天给大家介绍一个适合程序员的七夕“氛围感十足”的小礼物——借助华为图像服务,开发个超有爱七夕动图,它支持输入特殊关键词,触发“七夕”特效;同时,画面还可跟随指尖触碰产生动效……效果先睹为快↓↓↓
Demo效果
DSC0000.gif

有对象的秀给对象看,单身的朋友也可先做个七夕氛围组成员,方法到手,也许下次就用上啦。
话不多说,开整!
开发步骤
1.关键字动画播放
第一步:素材准备
首先找到一个合适的图片,这里我们选择了一张牛郎织女的图片:
DSC0001.png

然后将其中有动画效果的部件从图中取出来。我们取出了云朵,牛郎,织女,红心四个元素。
第二步:集成准备
先按照下面的指导完成开发者注册,创建应用,签名配置:
https://developer.huawei.com/consumer/cn/doc/development/Media-Guides/config-agc-0000001050199019?ha_source=hms1
再按照如下方式进行代码仓和编译依赖的配置:

  • 在项目级“build.gradle”文件中配置:
buildscript {
  repositories {
    google()
    jcenter()
    // 配置HMS Core SDK的Maven仓地址。
    maven {url 'https://developer.huawei.com/repo/'}
  }
  dependencies {
    ...
    // 增加agcp插件配置。
    classpath 'com.huawei.agconnect:agcp:1.4.2.300'
  }
}
allprojects {
  repositories {
    google()
    jcenter()
    // 配置HMS Core SDK的Maven仓地址。
    maven {url 'https://developer.huawei.com/repo/'}
  }
}

  • 在应用级“build.gradle”文件配置编译依赖(当前最新版本1.0.3.301):
dependencies { 
implementation 'com.huawei.hms:image-render: 1.0.3.301' 
  implementation 'com.huawei.hms:image-render-fallback: 1.0.3.301'
}

  • 配置权限
在“AndroidManifest.xml”文件中配置应用所需权限。
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
第三步:功能开发

  • 界面设计
这里用最简单的界面,一个FrameLayout中配置输入框和按钮:
DSC0002.png

我们将在这个FrameLayout中调试和展现动画。

  • 配置存储权限申请
在MainActivity的onCreate()方法中,检查是否拥有写存储的权限,如果缺少,就调用requestPermission方法,对WRITE_EXTERNAL_STORAGE权限进行申请:
int permissionCheck = ContextCompat.checkSelfPermission(ImageKitRenderDemoActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
initData();
initImageRender();
} else {
ActivityCompat.requestPermissions(ImageKitRenderDemoActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
}
如果已有权限,或权限申请成功后,对Image渲染模块进行初始化
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  if (requestCode == PERMISSION_REQUEST_CODE) {
    if (grantResults.length > 0
        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
      // The permission is granted.
      initData();
      initImageRender();
    } else {
      // The permission is rejected.
      Log.w(TAG, "permission denied");
      Toast.makeText(ImageKitRenderDemoActivity.this, "Please grant the app the permission to read the SD card", Toast.LENGTH_SHORT).show();
    }
  }
}

  • Image渲染模块初始化
获取渲染实例,初始化,并获取渲染视图。 这里会指定动画元素的目录:
ImageRender.getInstance(context, new ImageRender.RenderCallBack() {
    // 获取场景动效服务实例成功回调,返回场景动效服务实例
    @Override
    public void onSuccess(ImageRenderImpl imageRender) {
      imageRenderAPI = imageRender;
      if (imageRenderAPI != null) {
        int initResult = imageRenderAPI.doInit(sourcePath, Utils.getAuthJson());
        Log.i(TAG, "DoInit result == " + initResult);
        if (initResult == 0) {
          // Obtain the rendered view.
          RenderView renderView = imageRenderAPI.getRenderView();
          if (renderView.getResultCode() == ResultCode.SUCCEED) {
            View view = renderView.getView();
            if (null != view) {
              // Add the rendered view to the layout.
              contentView.addView(view);
              hashCode = String.valueOf(view.hashCode());
            } else {
              Log.w(TAG, "GetRenderView fail, view is null");
            }
      }
    }
    // 获取场景动效服务实例失败回调,返回错误码
    @Override
    public void onFailure(int errorCode) {
    ...
    }
  });

  • 配置关键字播放动画
还记得前面留下的输入框和按钮吗?我们使用关键字“Love”来进行动画播放。只需要通过imageRenderAPI.playAnimation()即可触发:
wordInput = findViewById(R.id.textinput);
enterBtn = findViewById(R.id.enter);
enterBtn.setOnClickListener(v -> {
  String inputContent = wordInput.getText().toString();
  if (inputContent.contentEquals("Love")) {
    if (null != imageRenderAPI) {
      imageRenderAPI. playAnimation();;
      wordInput.setVisibility(View.GONE);
      enterBtn.setVisibility(View.GONE);
    }
  } else {
    Toast.makeText(this,"再想想?",Toast.LENGTH_SHORT).show();
  }
});

  • 配置动画
框架搭好了,现在来到动画的部分。Image Kit提供了5种基础动效和9种高级动效,可以满足绝大部分场景的使用要求。
在这里我们使用到了透明度动画,位移动画,缩放动画,以及下落动效。
Image Kit的动画配置均在manifest.xml文件中完成。可不要和AndroidManifest.xml文件搞混了哦。
首先配置虚拟屏宽及背景图片。配置虚拟屏宽之后,系统会根据不同的分辨率对动画进行缩放,使效果保持一致。
<Root screenWidth="1080">
<Image src="background.png"/>
我们希望牛郎织女能够逐渐靠近直至相会,此时加入牛郎织女两个元素,分别配置动线,此时使用到位移动画的特效:
<Image x="1000" y="1450" src="man.png">
     <PositionAnimation repeat="1">
       <Position x="0" y="0" time="0"/>
       <Position x="-450" y="-100" time="4000"/>
     </PositionAnimation>
  </Image>
  <Image x="-600" y="800" src="woman.png">
    <PositionAnimation repeat="1">
      <Position x="0" y="0" time="0"/>
      <Position x="700" y="300" time="4000"/>
    </PositionAnimation>
  </Image>
这样牛郎织女将从屏幕两侧向中间靠近,直至相会。
相会之后在中心将出现跳动的红心,这里用到了透明度动画及缩放动画的叠加特效:
<Image x="520" y="1350"  src="heart.png" visibility="#show1">
    <AlphaAnimation delay="4000" repeat="1">
      <Alpha a="255" time="0"/>
      <Alpha a="0" time="3000"/>
    </AlphaAnimation>
    <SizeAnimation delay="4000" repeat="1">
      <Size w="127" h="95" time="0"/>
      <Size w="508" h="380" time="3000"/>
    </SizeAnimation>
  </Image>
到现在,关键元素已经有了,可是看起来还是有点干巴,要找点什么点缀一下。
天上的云朵也可以动起来,让它在小范围里动一下更灵动一些:
<Image x="150" y="200" src="cloud.png">
    <PositionAnimation repeat="0">
      <Position x="0" y="0" time="0"/>
      <Position x="-50" y="0" time="3000"/>
      <Position x="0" y="0" time="6000"/>
    </PositionAnimation>
  </Image>
想再罗曼蒂克一些,撒一些花瓣,这里用到的就是下落动效:
<DropPhysicalView gravityX="3" gravityY="10" airDensity="1000" delay="8800" visibility="#show2">
    <ItemGroup x="0" y="0" width="#screen_width" height="#screen_height">
      <Alpha x="0" y="#screen_height-1000" width="#screen_width" height="#screen_height" value="20"/>
      <Item count="20" src="follow.png">
        <Velocity isRandom="true" velocityX="0" velocityY="5"/>
        <Position isRandom="true"/>
        <AngleVelocity isRandom="true" angleVelocity="5"/>
        <Weight isRandom="true" value="0.5"/>
      </Item>
    </ItemGroup>
  </DropPhysicalView>

  • 到这里已经大功告成。最后可以再将动画保留下来
// 开始录制
int resultCode = imageRenderAPI.startRecord(json, new IStreamCallBack () {
  // 在录制成功回调中,将视频或GIF字节数组保存成mp4或GIF文件
  @Override
  void onRecordSuccess(HashMap<String, Object> map) {
    ...
    String recordType = (String) hashMap.get("recordType");
    byte[] videoBytes = (byte[]) hashMap.get("videoBytes");
    byte[] gifBytes = (byte[]) hashMap.get("gifBytes");
    try {
      if (recordType.equals("1")) {
        if (videoBytes != null) {
          // 保存mp4文件
          saveFile(videoBytes, mp4Path);
        }
      } else if (recordType.equals("2")) {
        ...
      } else if (recordType.equals("3")) {
        ...
      }
    } catch (IOException e) {
      ...
    }
    ...
  }
  // 录制失败回调
  @Override
  void onRecordFailure(HashMap<String, Object> map) {
    ...
  }
  // 录制进度回调,progress取值范围为0-100
  @Override
  void onProgress(int progress) {
    runOnUiThread(new Runnable() {
      @Override
      public void run() {
        textProgress.setText("当前录制进度:" + progress + "%");
      }
    });
  }
});
以上就得到最终效果啦~
除了动效之外,Image Kit还提供了滤镜功能,可以给图片添上浪漫的色彩,贴纸花字的功能,也可以给用户的图片增加爱情的元素。
了解更多>>
访问华为图像服务官网
访问华为开发者联盟官网
获取开发指导文档
华为移动服务开源仓库地址:GitHub、Gitee
关注我们,第一时间了解** HMS Core **最新技术资讯~