一个动态波浪纹Android界面
IndexActivity.java
package com.example.rubikrobot; import androidx.appcompat.app.AppCompatActivity; import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
import android.view.Window;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.Button;
import android.widget.ImageView; import java.util.ArrayList; public class IndexActivity extends AppCompatActivity {
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_index);
final RippleBackground rippleBackground=findViewById(R.id.content);
final Handler handler=new Handler(Looper.myLooper());
//foundDevice=(ImageView)findViewById(R.id.foundDevice);
button=findViewById(R.id.centerImage);
rippleBackground.startRippleAnimation();
Intent intent=new Intent();
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
intent.setClass(IndexActivity.this,MainActivity.class);
startActivity(intent);
}
}); }
}
RippleBackground.java
package com.example.rubikrobot; import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.RelativeLayout; import java.util.ArrayList; public class RippleBackground extends RelativeLayout{ private static final int DEFAULT_RIPPLE_COUNT=6;
private static final int DEFAULT_DURATION_TIME=3000;
private static final float DEFAULT_SCALE=6.0f;
private static final int DEFAULT_FILL_TYPE=0; private int rippleColor;
private float rippleStrokeWidth;
private float rippleRadius;
private int rippleDurationTime;
private int rippleAmount;
private int rippleDelay;
private float rippleScale;
private int rippleType;
private Paint paint;
private boolean animationRunning=false;
private AnimatorSet animatorSet;
private ArrayList<Animator> animatorList;
private LayoutParams rippleParams;
private ArrayList<RippleView> rippleViewList=new ArrayList<RippleView>(); public RippleBackground(Context context) {
super(context);
} public RippleBackground(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
} public RippleBackground(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
} private void init(final Context context, final AttributeSet attrs) {
if (isInEditMode())
return; if (null == attrs) {
throw new IllegalArgumentException("Attributes should be provided to this view,");
} final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RippleBackground);
rippleColor=typedArray.getColor(R.styleable.RippleBackground_rb_color, getResources().getColor(R.color.rippelColor));
rippleStrokeWidth=typedArray.getDimension(R.styleable.RippleBackground_rb_strokeWidth, getResources().getDimension(R.dimen.rippleStrokeWidth));
rippleRadius=typedArray.getDimension(R.styleable.RippleBackground_rb_radius,getResources().getDimension(R.dimen.rippleRadius));
rippleDurationTime=typedArray.getInt(R.styleable.RippleBackground_rb_duration,DEFAULT_DURATION_TIME);
rippleAmount=typedArray.getInt(R.styleable.RippleBackground_rb_rippleAmount,DEFAULT_RIPPLE_COUNT);
rippleScale=typedArray.getFloat(R.styleable.RippleBackground_rb_scale,DEFAULT_SCALE);
rippleType=typedArray.getInt(R.styleable.RippleBackground_rb_type,DEFAULT_FILL_TYPE);
typedArray.recycle(); rippleDelay=rippleDurationTime/rippleAmount; paint = new Paint();
paint.setAntiAlias(true);
if(rippleType==DEFAULT_FILL_TYPE){
rippleStrokeWidth=0;
paint.setStyle(Paint.Style.FILL);
}else
paint.setStyle(Paint.Style.STROKE);
paint.setColor(rippleColor); rippleParams=new LayoutParams((int)(2*(rippleRadius+rippleStrokeWidth)),(int)(2*(rippleRadius+rippleStrokeWidth)));
rippleParams.addRule(CENTER_IN_PARENT, TRUE); animatorSet = new AnimatorSet();
animatorSet.setInterpolator(new AccelerateDecelerateInterpolator());
animatorList=new ArrayList<Animator>(); for(int i=0;i<rippleAmount;i++){
RippleView rippleView=new RippleView(getContext());
addView(rippleView,rippleParams);
rippleViewList.add(rippleView);
final ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(rippleView, "ScaleX", 1.0f, rippleScale);
scaleXAnimator.setRepeatCount(ObjectAnimator.INFINITE);
scaleXAnimator.setRepeatMode(ObjectAnimator.RESTART);
scaleXAnimator.setStartDelay(i * rippleDelay);
scaleXAnimator.setDuration(rippleDurationTime);
animatorList.add(scaleXAnimator);
final ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(rippleView, "ScaleY", 1.0f, rippleScale);
scaleYAnimator.setRepeatCount(ObjectAnimator.INFINITE);
scaleYAnimator.setRepeatMode(ObjectAnimator.RESTART);
scaleYAnimator.setStartDelay(i * rippleDelay);
scaleYAnimator.setDuration(rippleDurationTime);
animatorList.add(scaleYAnimator);
final ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(rippleView, "Alpha", 1.0f, 0f);
alphaAnimator.setRepeatCount(ObjectAnimator.INFINITE);
alphaAnimator.setRepeatMode(ObjectAnimator.RESTART);
alphaAnimator.setStartDelay(i * rippleDelay);
alphaAnimator.setDuration(rippleDurationTime);
animatorList.add(alphaAnimator);
} animatorSet.playTogether(animatorList);
} private class RippleView extends View{ public RippleView(Context context) {
super(context);
this.setVisibility(View.INVISIBLE);
} @Override
protected void onDraw(Canvas canvas) {
int radius=(Math.min(getWidth(),getHeight()))/2;
canvas.drawCircle(radius,radius,radius-rippleStrokeWidth,paint);
}
} public void startRippleAnimation(){
if(!isRippleAnimationRunning()){
for(RippleView rippleView:rippleViewList){
rippleView.setVisibility(VISIBLE);
}
animatorSet.start();
animationRunning=true;
}
} public void stopRippleAnimation(){
if(isRippleAnimationRunning()){
animatorSet.end();
animationRunning=false;
}
} public boolean isRippleAnimationRunning(){
return animationRunning;
}
}
layout
<?xml version="1.0" encoding="utf-8"?>
<com.example.rubikrobot.RippleBackground
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#A2DAEC"
android:id="@+id/content"
app:rb_color="#0099CC"
app:rb_radius="32dp"
app:rb_rippleAmount="6"
app:rb_duration="3000"
app:rb_scale="6">
<Button
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_centerInParent="true"
android:id="@+id/centerImage"
android:text="启动"
android:textColor="@color/white"
android:background="@drawable/ic_blue"
/>
</com.example.rubikrobot.RippleBackground>
效果图:
这是三个主要文件,剩下的没有展示。
链接:Github
参考文档以及链接均来自于:【Android开发】安卓炫酷效果集合
一个动态波浪纹Android界面的更多相关文章
- 跟Google学习Android开发-起始篇-用碎片构建一个动态的用户界面(3)
4.3 构建一个灵活的用户界面 当设计你的应用程序要支持大范围的屏幕尺寸时,你可以在不同的布局配置中重用碎片,来根据可用的屏幕空间优化用户体验. 例如,在手持设备上,它可能是适应来在一个单窗格用户界面 ...
- android 界面设计基本知识Ⅲ
本章继续讲述在android界面设计中相关的知识点.介绍内容包括BroadcastReceiver(广播),Service(服务),Widget(小部件),WebView(网页加载控件). 1.Bro ...
- android 界面设计基本知识Ⅱ
上一章讲述了Android界面设计时,一些基本控件的使用,本章主要讲述自定义控件,Fragment和Headler线程机制. 1.自定义控件 (1)基本知识 dp.sp和dx px:像素点 ...
- 使用HTML来生产Android界面
使用HTML来生产Android界面 (2013-03-11 17:50:39) 转载▼ 分类: Android 1. HTML 开发软件界面 因为android软件开发分工目前还没有细化,程 ...
- 让我们一起来做最漂亮的Android界面吧!
让我们一起来做最漂亮的Android界面吧! AndroidiOS产品设计 摘要:如何为Android设备量身定制以打造出最为完美的应用?这是让诸多开发者很是头疼的问题.不同于iOS,Android设 ...
- 打造一个高逼格的android开源项目——小白全攻略 (转)
转自:打造一个高逼格的android开源项目 小引子 在平时的开发过程中,我们经常会查阅很多的资料,最常参考的是 github 的开源项目.通常在项目的主页面能看到项目的简介和基本使用,并且时不时能看 ...
- [虾扯蛋] android界面框架-Window
从纯sdk及framwork的角度看,android中界面框架相关的类型有:Window,WindowManager,View等.下面就以这几个类为出发点来概览下安卓开发的"界面架构&quo ...
- 关于jni编译32位、64位动态库(Android.mk和Application.mk文件)
最近新项目需要编译64位的动态库,这里记录如何配置. 在jni目录下加入Android.mk和Application.mk文件. Application.mk APP_ABI := armeabi a ...
- Android界面组件的四种启动方式
Android界面组件启动有四种方式 standard,singleTop,singleTask,singleInstance. standard:每次调用都会都会产生新的组件. singletop: ...
随机推荐
- List、Set、Map有什么异同(详解)
引言:Java集合框架提供了一套性能优良.使用方便的接口和类,它们位于java.util包中 Java集合框架(常用接口): Collection 接口存储一组不唯一,无序的对象(父类接口 ...
- 01-Servlet 回顾
通过url访问资源有三个步骤: 接收请求 处理请求 响应请求 web服务器:将某个主机上的资源映射为一个URL供外界访问,完成接收和响应请求 servlet容器:存放着servlet对象(由程序员编程 ...
- 小程序授权登录并 laravel7(laravel8) token 应用
参考博客: https://blog.csdn.net/qq_42839386/article/details/118279530 1:composer 下载 composer require fir ...
- VUE-表单验证
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- scoped样式
scoped样式 作用∶让样式在局部生效防止冲突 写法∶<style scoped> 比如School组件和Student组件的样式名一样,当组件汇总到一起时样式会冲突.所以加上scope ...
- 安装ncclient出现rust版本不对问题解决
在windows上安装ncclient的时候,出现了提示说rust版本需要至少1.14.0以上版本 解决办法: 在https://www.rust-lang.org/tools/install下载新版 ...
- mysql 锁表
mysql 查看锁表解锁-- 查看那些表锁到了show OPEN TABLES where In_use > 0;-- 查看进程号show processlist;--删除进程 kill 108 ...
- 论如何在使用RedisStandaloneConfiguration时让JedisConnectionFactory用上JedisPoolConfig
前言 公司项目上线后经常运行一两天后就会出现延时.无响应的情况,当时第一反应觉得可能是某些业务优化不行,检查业务也没发现有什么问题,前前后后倒是修了两三个BUG,本以为没啥事儿了,但也就好了两天,很奇 ...
- .net为程序集签名之.pfx文件
项目中误删了.pfx证书文件,导致项目无法启动. 以为很快就能在网上找到解决方案,应该没关系,不过找了半个小时,都没有有效的解决办法,搜出来很多.pfx文件是一个证书文件,里面存储公钥和私钥,对于我要 ...
- kubernetes证书过期处理
rancher中文文档:http://docs.rancher.cn/ k8s中文文档:https://kubernetes.io/zh/docs 一.修改kubeadm 源码 增加证书到100年 $ ...