Android第十三讲笔记(动画入门,开源控件,应用程序打包)
Posted a碟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android第十三讲笔记(动画入门,开源控件,应用程序打包)相关的知识,希望对你有一定的参考价值。
目录
1.动画
在我们的APP中很多地方都会用到动画,像下图的点赞等等都用到了动画
android 中一共有三种方式来播放动画:
1.帧动画,像一般的 gif 图我们就可以把它看作一个帧动画的过程。在Android中,帧动画的本质是把一组预先准备好的图片循环切换播放,造成一种动画效果。
但是其消耗内存高。
2.补间动画,实际上安卓的大部分动画效果以前都是用补间动画来完成的
3.属性动画,可以说是完全替代了补间动画
我们今天讲的是安卓中使用最多的动画,属性动画。
动画到底由哪些东西组成?
- 控件透明度发生变化,不透明->透明。
- 缩放动画,控件大小变化
- 位移动画,位置发生移动
- 旋转动画
任何复杂的动画都能由上述几种动画组合而成。
1.案例一–四种简单动画
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="17dp"
android:text="缩放动画"
app:layout_constraintStart_toStartOf="@+id/button"
app:layout_constraintTop_toBottomOf="@+id/button" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="60dp"
android:text="透明度动画"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="17dp"
android:layout_marginEnd="3dp"
android:layout_marginRight="3dp"
android:text="位移动画"
app:layout_constraintEnd_toEndOf="@+id/button2"
app:layout_constraintTop_toBottomOf="@+id/button2" />
<Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="17dp"
android:text="旋转动画"
app:layout_constraintStart_toStartOf="@+id/button3"
app:layout_constraintTop_toBottomOf="@+id/button3" />
<ImageView
android:id="@+id/imageView"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="35dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView"
app:srcCompat="@drawable/love" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java代码
里面实现了简单的动画
ObjectAnimator.ofFloat参数
1.对哪个对象进行动画操作 2.动画需要执行的属性 3.动画的值的范围
package com.hnucm.android_66;
import androidx.appcompat.app.AppCompatActivity;
import android.animation.ObjectAnimator;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
ImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView=findViewById(R.id.imageView);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 透明度动画
//
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView,"alpha",1,0);
// 设置动画的时间
objectAnimator.setDuration(5000);
objectAnimator.start();
}
});
findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 缩放动画
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView,"scaleX",0.5f,2);
objectAnimator.setDuration(5000);
objectAnimator.start();
}
});
findViewById(R.id.button3).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 位移动画
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView,"translationX",-200,200);
objectAnimator.setDuration(5000);
objectAnimator.start();
}
});
findViewById(R.id.button4).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 旋转动画
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView,"rotation",0,720);
objectAnimator.setDuration(5000);
objectAnimator.start();
}
});
}
}
2.案例二–复杂动画
实现了透明度的变化和位移的动画
使用方法和上面的简单动画一致
// 组动画
ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(imageView,"alpha",1,0);
ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(imageView,"scaleX",0,2);
ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(imageView,"scaleY",0,2);
AnimatorSet animatorSet = new AnimatorSet();//set中元素不重复
animatorSet.play(objectAnimator1)
.with(objectAnimator2)
.with(objectAnimator3);
animatorSet.setDuration(2000);
animatorSet.start();
2.开源控件
1.实现圆角+阴影效果(CardView)
<com.google.android.material.card.MaterialCardView
android:layout_width="0dp"
android:layout_height="300dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:cardCornerRadius="20dp"
app:cardElevation="10dp"
app:layout_constraintTop_toBottomOf="@+id/textView">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_marginStart="116dp"
android:layout_marginLeft="116dp"
android:layout_marginTop="36dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/fruit" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="28dp"
android:text="西瓜"
android:textSize="20dp"
app:layout_constraintEnd_toEndOf="@+id/imageView"
app:layout_constraintStart_toStartOf="@+id/imageView"
app:layout_constraintTop_toBottomOf="@+id/imageView" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
在CardView中,遵循的是帧布局的原则,没学帧布局的同学,在CardView中直接用一个constraintlayout布局或者自己会用的布局,将需要用的控件包在里面就好了。
app:cardCornerRadius="20dp"
app:cardElevation="10dp"
这两个属性一个是设置圆角,一个是设置阴影。
2.图片选择和相机拍照
1.前期准备(获取权限,导入依赖)
图片选择框架依赖
implementation 'io.github.lucksiege:pictureselector:v2.7.2'
增加文件读写的权限
第三个是照相机的权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
还要加上这句话
android:requestLegacyExternalStorage="true"
不加可能在高版本的手机上能用,但在低版本上可能用不了
文件的读写权限和我们以前学习的网络权限等等有些区别,它属于危险权限
危险权限和普通权限
从 Android6.0 开始,Google调整了应用的权限申请方案。调整之后将权限分级,分成了普通权限和危险权限
- 普通权限的授权方式跟之前一样,只需要在 Manifest 文件中申明即可
- 危险权限不仅需要在 Manifest 文件中声明,还需要在程序中调用官方提供的Api主动申请
危险权限有如下九种:读取联系人;打电话;读取用户日历信息;相机权限;传感器,获取用户位置;读取用户SD卡(拍的照片视频都在这里);多媒体(录音);短信。
那么让用户同意权限的弹窗如何调出来呢,我们使用第三方开源控件
首先导入依赖 申请危险权限
implementation 'com.yanzhenjie:permission:2.0.3'
这个开源控件支持的SDK的最低版本是19,所以我们可以修改
获取权限的案例
AndPermission.with(this)
.runtime()
.permission(Permission.WRITE_EXTERNAL_STORAGE, Permission.CAMERA)
.onGranted(permissions -> {
Toast.makeText(MainActivity2.this, "授权成功!", Toast.LENGTH_SHORT).show();
})
.onDenied(permissions -> {
//用户拒绝->强制退出app
Toast.makeText(MainActivity2.this, "未获取权限不能使用本app!", Toast.LENGTH_SHORT).show();
System.exit(0);
})
.start();
如果用户不允许以上权限,用户拒绝,市面上大多数APP则会直接退出。
2.读取用户相册
建GlideEngine.java类
官方代码,直接使用
package com.hnucm.android_66;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.graphics.drawable.RoundedBitmapDrawable;
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.BitmapImageViewTarget;
import com.bumptech.glide.request.target.ImageViewTarget;
import com.luck.picture.lib.engine.ImageEngine;
import com.luck.picture.lib.listener.OnImageCompleteCallback;
import com.luck.picture.lib.tools.MediaUtils;
import com.luck.picture.lib.widget.longimage.ImageSource;
import com.luck.picture.lib.widget.longimage.ImageViewState;
import com.luck.picture.lib.widget.longimage.SubsamplingScaleImageView;
public class GlideEngine implements ImageEngine {
/**
* 加载图片
*
* @param context
* @param url
* @param imageView
*/
@Override
public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) {
Glide.with(context)
.load(url)
.into(imageView);
}
/**
* 加载网络图片适配长图方案
* # 注意:此方法只有加载网络图片才会回调
*
* @param context
* @param url
* @param imageView
* @param longImageView
* @param callback 网络图片加载回调监听 {link after version 2.5.1 Please use the #OnImageCompleteCallback#}
*/
@Override
public void loadImage(@NonNull Context context, @NonNull String url,
@NonNull ImageView imageView,
SubsamplingScaleImageView longImageView, OnImageCompleteCallback callback) {
Glide.with(context)
以上是关于Android第十三讲笔记(动画入门,开源控件,应用程序打包)的主要内容,如果未能解决你的问题,请参考以下文章
Unity 入门笔记 - 05 - 动画事件&类&音效&对话框