当前位置:网站首页>三种实现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
边栏推荐
- pycharm Install packages failed
- SQL中 with函数的详解与用法
- 窗口分析函数LAST_VALUE,FIRST_VALUE,lag,lead
- sys.dbms_scheduler.create_job创建定时任务(功能更强大丰富)
- ORACLE表有逻辑坏块时EXPDP导出报错排查
- JVM basics you should know
- Using Prom label proxy to implement label based multi tenant reading of Prometheus thanos
- Component learning
- Arranges the objects specified in the array in front of the array
- ARGB透明度换算
猜你喜欢

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

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

实习做了啥

Build an OSS based image sharing website - polite feedback

AVD Pixel_2_API_24 is already running.If that is not the case, delete the files at C:\Users\admi

Build a cloud blog based on ECS (polite experience)

Oracle Job定时任务的使用详解

Winter combat camp hands-on combat - MySQL database rapid deployment practice lead mouse cloud Xiaobao

Construire un blog Cloud basé sur ECS (bénédiction sur le Code Cloud Xiaobao, explication détaillée de la tâche iphone13 gratuite)

Dolphinscheduler调度spark任务踩坑记录
随机推荐
Prometheus monitoring method and index interpretation of influxdb
js时间获取本周一、周日,判断时间是今天,今天前、后
SQL中 with函数的详解与用法
Chaos takes you to the chaos project quickly
Django::Did you install mysqlclient?
Oracle RAC数据库实例启动异常问题分析IPC Send timeout
测试oracle库700万数据量普通方式创建索引所需时间
Abnormal record-20
Oracle和mysql批量查询用户下所有表名和表名注释
Abnormal record-10
JS 比较2个数组中不同的元素
19C环境ORA-01035登陆报错处理
个人博客网站搭建
TC ebpf practice
Exception record-9
oracle表空间表分区详解及oracle表分区查询使用方法
Apprentissage par composantes
Encapsulate a set of project network request framework from 0
Build a cloud blog based on ECS (polite experience)
Chaos vous emmène au projet chaos.