当前位置:网站首页>三种实现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
边栏推荐
- Apprentissage par composantes
- Chaos takes you to the chaos project quickly
- oracle计算两日期相差多少秒,分钟,小时,天
- Thanos compact component test summary (processing historical data)
- Implementation of multi tenant read and write in Prometheus cortex
- Chaos带你快速上手混沌工程
- JS format current time and date calculation
- Chaos帶你快速上手混沌工程
- 10g数据库使用大内存主机时不能启动的问题
- Oracle索引状态查询与索引重建
猜你喜欢
Try catch cannot catch asynchronous errors
qs. In the stringify interface, the input parameter is converted into a & connected string (with the application / x-www-form-urlencoded request header)
接口幂等性问题
Prometheus thanos Quick Guide
Dolphinscheduler源码包src.tar.gz解压问题
Static interface method calls are not supported at language level ‘5‘ 异常解决
Winter combat camp hands-on combat - MySQL database rapid deployment practice lead mouse cloud Xiaobao
Using Prom label proxy to implement label based multi tenant reading of Prometheus thanos
Apache Atlas 编译及安装记录
mysql和pgsql时间相关操作
随机推荐
Memcached source code analysis
Abnormal record-18
Winter combat camp hands-on combat - cloud essential environment preparation, hands-on practical operation, quickly build lamp environment, lead mouse cloud Xiaobao backpack without shadow
个人博客网站搭建
useReducer基本用法
Abnormal record-22
iTOP4412 FramebufferNativeWindow(4.0.3_r1)
How does thanos configure different data retention durations for different tenants
oracle 修改默认临时表空间
Exception record-5
Abnormal record-16
RAC环境数据库节点参数设置不当导致监听无法连接问题排查
Abnormal record-15
[exynos4412] [itop4412] [android-k] add product options
解决::Argument ‘radius‘ is required to be an integer
专用窗口函数rank, dense_rank, row_number
开篇:双指针仪表盘的识别
Practice using polardb and ECs to build portal websites
Dolphinscheduler调度sql任务建表时The query did not generate a result set异常解决
JS function package foreach use return can not jump out of the outer function