当前位置:网站首页>三种实现ImageView以自身中心为原点旋转的方法
三种实现ImageView以自身中心为原点旋转的方法
2022-04-23 06:07:00 【小叶很笨呐!】
总结三种实现ImageView以自身中心为原点旋转的方法

资源链接:加载等待–阿里云盘
三个layout文件用到的控件都是一样的,所以这里就只贴出一个
main_activty.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">
<ImageView android:id="@+id/img_loading" android:layout_width="160dp" android:layout_height="160dp" android:src="@mipmap/loading_01" android:layout_marginTop="8dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
<Button android:id="@+id/btn_start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:text="开启" app:layout_constraintEnd_toEndOf="@+id/img_loading" app:layout_constraintStart_toStartOf="@+id/img_loading" app:layout_constraintTop_toBottomOf="@+id/img_loading" />
<Button android:id="@+id/btn_stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="关闭" android:layout_marginTop="8dp" app:layout_constraintEnd_toEndOf="@+id/btn_start" app:layout_constraintStart_toStartOf="@+id/btn_start" app:layout_constraintTop_toBottomOf="@+id/btn_start" />
</androidx.constraintlayout.widget.ConstraintLayout>
方法一:通过动画的方式来实现(最简单的一种)
如果想进一步了解动画相关知识,建议点击下方连接跳转到官网学习
动画简介 | Android 开发者 | Android Developers
java代码
注意:此方法只有一张图片,是在布局文件中插入到IamgeView中的
public class Test01Activity extends AppCompatActivity {
private static final String TAG = "Test01Activity";
private ImageView mImgLoading;
private Button mBtnStart;
private Button mBtnStop;
private Animation mRotate;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test01);
initView();
// 初始化旋转动画对象
// fromDegrees:起始角度的度数,toDegrees:结束角度度数,正数表示顺时针,负数表示逆时针
// pivotX:旋转中心的X坐标,pivotXValue:50%表示在object的中心
// pivotY:与pivotX同理
mRotate = new RotateAnimation(
0f,
360f,
Animation.RELATIVE_TO_SELF,
0.5f,
Animation.RELATIVE_TO_SELF,
0.5f);
// 初始话插值器并设置线性插值器,变化率,并不是运行速度。一个插补动画,可以将动画效果设置为加速、减速、反复、反弹等
//linearInterpolator为匀速
mRotate.setInterpolator(new LinearInterpolator());
// 设置动画从fromDegrees转动到toDegrees花费的时间,毫秒。可以用来计算速度
mRotate.setDuration(2000);
// 设置重复的次数(旋转圈数),Animation.INFINITE = -1,无限循环
mRotate.setRepeatCount(Animation.INFINITE);
mBtnStart.setOnClickListener(v -> {
mImgLoading.setAnimation(mRotate);
// 注意这里,在设置完动画一定要start动画才会执行
mImgLoading.startAnimation(mRotate);
});
mBtnStop.setOnClickListener(v -> {
mImgLoading.clearAnimation();
});
}
private void initView() {
mImgLoading = findViewById(R.id.img_loading);
mBtnStart = findViewById(R.id.btn_start);
mBtnStop = findViewById(R.id.btn_close);
}
}
也可以通过ObjectAnimator属性动画来实现
private ObjectAnimator mAnimator;
// Object target:目标对象,
// String propertyName:指定要改变对象的什么属性,这个属性名要求在对应对象中必须有对应的public的PsetPropertyName的方法。如上面的rotation就要求ImageView中必须有setRotation方法才行。
// float... values:一系列这个属性将会到达的值
mAnimator = ObjectAnimator.ofFloat(mImgLoading,"rotation",0f,360f);
// 设置一次动画的时间
mAnimator.setDuration(2000);
// 设置插值器,用来控制变化率
mAnimator.setInterpolator(new LinearInterpolator());
// 设置重复的次数,无限
mAnimator.setRepeatCount(ObjectAnimator.INFINITE);
mAnimator.start();
// 在合适的位置调用 mAnimator.pause()方法进行暂停操作
方法二:Timer+Handler
java代码
public class Test02Activity extends AppCompatActivity {
private ImageView mImgLoading;
private Button mBtnStart;
private Button mBtnStop;
// 初始化存放图片的数组
private int[] mImgS = new int[] {
R.mipmap.loading_01,R.mipmap.loading_02,R.mipmap.loading_03,R.mipmap.loading_04,R.mipmap.loading_05,
R.mipmap.loading_06,R.mipmap.loading_07,R.mipmap.loading_08,R.mipmap.loading_09,R.mipmap.loading_10,
R.mipmap.loading_11,R.mipmap.loading_12
};
private int mImgStart = 0;
private Handler mHandler;
private Timer mTimer;
private TimerTask mTimerTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test02);
initView();
mHandler = new Handler(Looper.myLooper()) {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
if (msg.what == 333) {
mImgLoading.setImageResource(mImgS[mImgStart++ % 12]);
}
}
};
mBtnStart.setOnClickListener(v -> {
// https://blog.csdn.net/wuqingsen1/article/details/84875785
// 倒计时的操作博客
mTimer = new Timer();
mTimerTask = new TimerTask() {
// 周期执行一个任务
@Override
public void run() {
mHandler.sendEmptyMessage(333);
}
};
// delay:表示多长时间后开始执行(延时)
// period:执行的周期,这里就是表示,200毫秒为一周期执行
mTimer.schedule(mTimerTask,0,200);
/** * schedule的几种参数及用法: * 1、表示在指定的时间执行一次 * schedule(timerTask,time); * 2、firstTime为Date类型,表示从firstTime时刻开始,每隔period毫秒执行一次 * schedule(task,firstTime,period) * 3、延时delay毫秒数后开始执行一次 * schedule(timeTask,delay) * 4、从现在延时delay毫秒后,每个period毫秒执行一次 * schedule(timeTask,delay,period) */
});
mBtnStop.setOnClickListener(v -> {
// 正确的停止方法是判空
if (mTimerTask != null) {
mTimerTask.cancel();
mTimerTask = null;
}
if (mTimer != null) {
mTimer.cancel();
mTimer = null;
}
});
}
private void initView() {
mImgLoading = findViewById(R.id.img_loading);
mBtnStart = findViewById(R.id.btn_start);
mBtnStop= findViewById(R.id.btn_stop);
}
}
方法三:Handler + Thread的的方法(不推荐)
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private ImageView mImgLoading;
private Button mBtnStart,mBtnStop;
// 用于判断当前为转动还是停止
private Boolean isPause = false;
// 用于标识转动到第几个
private int flag = 1;
private Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initThread();
initHandler();
mBtnStart.setOnClickListener(v -> {
isPause = true;
});
mBtnStop.setOnClickListener(v -> {
isPause = false;
});
}
private void initThread() {
new Thread(new Runnable() {
@Override
public void run() {
// 一直进行判断,循环的开启与关闭通过isPause来控制
while (true) {
if (isPause) {
// 获得message对象
Message msg = Message.obtain();
// 将flag赋值给msg.what
msg.what = flag;
// 将待带有flag的消息发出
mHandler.sendMessage(msg);
// 因为我们有6张图片,所以当flag为6时,循环为第一张图片
if (flag == 6) {
flag = 1;
}
flag++;
}
// 延时操作
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 开启线程
}).start();
}
private void initHandler() {
mHandler = new Handler(Looper.myLooper()) {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
// 在这里获取消息的值,也就是初始化线程中我们通过msg.what传入的值
// 我们的延时在这里达到了每隔50毫秒就发送过来一条msg.what == flag++的消息
switch (msg.what) {
// 顺序设置图片,达到图片转动的效果
case 1:
mImgLoading.setImageResource(R.mipmap.loading_01);
break;
case 2:
mImgLoading.setImageResource(R.mipmap.loading_02);
break;
case 3:
mImgLoading.setImageResource(R.mipmap.loading_03);
break;
case 4:
mImgLoading.setImageResource(R.mipmap.loading_04);
break;
case 5:
mImgLoading.setImageResource(R.mipmap.loading_05);
break;
case 6:
mImgLoading.setImageResource(R.mipmap.loading_06);
break;
default:
Log.d(TAG,"default is load");
}
}
};
}
private void initView() {
mImgLoading = findViewById(R.id.img_loading);
mBtnStart = findViewById(R.id.btn_start);
mBtnStop= findViewById(R.id.btn_stop);
}
}
方法三为从别人的博客学来的,找不到原文链接了,如有冒犯,烦请私信我。
版权声明
本文为[小叶很笨呐!]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_50957373/article/details/124329934
边栏推荐
- Build an OSS based image sharing website - polite feedback
- [Exynos4412][iTOP4412][Android-K]添加产品选项
- Dolphinscheduler源码包src.tar.gz解压问题
- Oracle RAC数据库实例启动异常问题分析IPC Send timeout
- BCC installation and basic tool instructions
- RAC环境集群组件gpnp未启动成功问题分析
- 统一任务分发调度执行框架
- Apache Atlas 编译及安装记录
- Ali vector library Icon tutorial (online, download)
- Oracle Job定时任务的使用详解
猜你喜欢

Apache Atlas 编译及安装记录

专用窗口函数rank, dense_rank, row_number

Prometheus cortex Architecture Overview (horizontally scalable, highly available, multi tenant, long-term storage)

窗口分析函数LAST_VALUE,FIRST_VALUE,lag,lead

Chaos帶你快速上手混沌工程

iTOP4412 HDMI显示(4.4.4_r1)

Winter combat camp hands-on combat - first understand the cloud foundation, hands-on practice ECS ECS ECS novice on the road to get the mouse cloud Xiaobao backpack shadowless

this.getOptions is not a function

Encapsulate a set of project network request framework from 0

Itop4412 HDMI display (4.0.3_r1)
随机推荐
[sm8150] [pixel4] LCD driver
Implementation of multi tenant read and write in Prometheus cortex
Prometheus thanos Quick Guide
Apache SeaTunnel 2.1.0部署及踩坑
Chaos vous emmène au projet chaos.
测试oracle库700万数据量普通方式创建索引所需时间
Winter combat camp hands-on combat - first understand the cloud foundation, hands-on practice ECS ECS ECS novice on the road to get the mouse cloud Xiaobao backpack shadowless
Cause: dx.jar is missing
Dolphinscheduler源码包src.tar.gz解压问题
Apache Atlas 编译及安装记录
iTOP4412 SurfaceFlinger(4.4.4_r1)
Android-Room数据库快速上手
iTOP4412内核反复重启
Abnormal record-19
微服务架构核心概念
SQL中 with函数的详解与用法
oracle用delete删除数据所需时间测试
Dolphinscheduler配置Datax踩坑记录
Winter combat camp hands-on combat - MySQL database rapid deployment practice lead mouse cloud Xiaobao
RAC环境alert日志报错Drop transient type: SYSTP2JW0acnAurDgU1sBqMBryw==的排查