自定义Dialog加载动画

本文介绍了如何在Android中创建自定义Dialog加载动画。首先在res/anim文件夹下创建frame.xml帧动画,接着结合之前的登录例子,将动画应用到自定义的加载对话框中。在layout中创建progress_dialog.xml布局,并通过新建的CustomProgressDialog类,继承ProgressDialog以实现可复用的自定义动画对话框。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<pre name="code" class="java">在上篇文章中介绍了模拟登录服务器时出现的加载对话框,不过是使用android 默认的Dialog,那么我们如果想用自己定义的怎么实现呢?下面先讲android的帧动画:

 

     首先是新建一项目,然后在res底下新建一个anim文件夹,新建一个frame.xml(名称自取)文件,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<!--animation-list 动画帧列表 item:每一帧,duration="200" 200毫秒,0.2秒,根据自己情况可以调节  -->
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false" >
    <item
        android:drawable="@drawable/img01"
        android:duration="200"/>
    <item
        android:drawable="@drawable/img02"
        android:duration="200"/>
    <item
        android:drawable="@drawable/img03"
        android:duration="200"/>
    <item
        android:drawable="@drawable/img04"
        android:duration="200"/>
    <item
        android:drawable="@drawable/img05"
        android:duration="200"/>
    <item
        android:drawable="@drawable/img06"
        android:duration="200"/>
    <item
        android:drawable="@drawable/img07"
        android:duration="200"/>
    <item
        android:drawable="@drawable/img08"
        android:duration="200"/>
</animation-list>


对了,忘记说了,先准备动画图片,等会附件里源码会有,然后再修改layout底下的activity_main.xml文件,代码如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
	android:gravity="center"
    tools:context="com.example.animationtest.MainActivity" >
    <ImageView
        android:id="@+id/imageview1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@anim/frame"/>
        <TextView
        android:id="@+id/textview1"
        android:layout_below="@id/imageview1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="30dip"
        android:text="@string/text_str" />

        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/textview1"
            android:layout_below="@+id/textview1"
            android:layout_marginTop="51dp"
            android:text="开始" />

</RelativeLayout>
布局文件都修改好了,然后再看java文件代码:

package com.example.animationtest;

import android.app.Activity;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

/**
 * 小P优优奔跑动画
 * @author easy
 *
 */
public class MainActivity extends Activity {
	//定义动画
	 private AnimationDrawable mAnimation;
	 private ImageView imageview1;
	 private TextView textview1;
	 private Button button1;
	 //记录奔跑的旗帜
	 private static boolean flag=true;
	 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageview1 = (ImageView) findViewById(R.id.imageview1);
        textview1 = (TextView) findViewById(R.id.textview1);
        button1 = (Button) findViewById(R.id.button1);
        button1.setOnClickListener(new OnClickListener(){

			@Override
			public void onClick(View v) {
				// 通过ImageView对象拿到背景显示的AnimationDrawable,必须这一步,实例化动画
				mAnimation = (AnimationDrawable) imageview1.getBackground();
				//开个线程跑起来
				imageview1.post(new Runnable() {
					@Override
					public void run() {
						if(flag){
						mAnimation.start();
						button1.setText("停止");
						textview1.setText("正在奔跑中!");
						flag=false;
						}else{
							mAnimation.stop();
							button1.setText("开始");
							textview1.setText("正在休息中!");
							flag=true;
						}
					}
				});
				
			}
        	
        });
    }

}

最后运行跑起来!



以上就是android animation帧动画的小例子,下面我们再把上一篇文章介绍的登录例子结合起来,实现自定义加载对话框

在上一篇的源码中直接添加,当然这里是当作dialog来处理,而不是主activty页面,所以在layout里面另创建一个progress_dialog.xml文件,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
   android:layout_gravity="center"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/loadingIv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@anim/frame"/>

    <TextView
        android:id="@+id/loadingTv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
		android:layout_below="@id/loadingIv"
		android:layout_centerHorizontal="true"
		android:textSize="16sp"
        android:text="正在加载中.." />

</RelativeLayout>

我们要养成良好习惯,写代码一定要体现出能复用的价值,所以这里把实现自定义动画的对话框布局分离出来,新建一个CustomProgressDialog继承ProgressDialog,实现代码:

package com.example.progressdialogdemo;

import android.app.ProgressDialog;
import android.content.Context;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.progressdialogdemo.R;

/**
 * @Description:自定义对话框
 */
public class CustomProgressDialog extends ProgressDialog {

	private AnimationDrawable mAnimation;
	private ImageView mImageView;
	private String mLoadingTip;
	private TextView mLoadingTv;
	private int mResid;
/**
 * 
 * @param context 上下文
 * @param content  提示信息
 * @param id 布局的ID
 */
	public CustomProgressDialog(Context context, String content, int id) {
		super(context);
		this.mLoadingTip = content;
		this.mResid = id;
		//触摸动画之外的地方是否取消动画,这里设置为flase不取消;
		setCanceledOnTouchOutside(false);
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		initView();
		initData();
	}
//调用时初始化数据
	private void initData() {

		mImageView.setBackgroundResource(mResid);
		// 通过ImageView对象拿到背景显示的AnimationDrawable
		mAnimation = (AnimationDrawable) mImageView.getBackground();
		// 为了防止在onCreate方法中只显示第一帧的解决方案之一
		mImageView.post(new Runnable() {
			@Override
			public void run() {
				mAnimation.start();
			}
		});
		mLoadingTv.setText(mLoadingTip);
	}
//调用时初始化布局
	private void initView() {
		setContentView(R.layout.progress_dialog);
		mLoadingTv = (TextView) findViewById(R.id.loadingTv);
		mImageView = (ImageView) findViewById(R.id.loadingIv);
	}
	/**
	 *  可以看到在代码中,我们使用到一个imageview.post(Runnable r)方法,因为帧动画需要不断的重画,所以必须在线程中运行,
	 *  否则只能看到第一帧的效果,这和我们做游戏的原理是一样的,一个人物的走动,是有线程在控制图片的不断重画。
	 *  这个方法onWindowFocusChanged也可以实现,用哪一个也可以
	 * 这个onWindowFocusChanged指的是这个Activity得到或者失去焦点的时候 就会call,监听actvity焦点的
	 * 不过通过这个事件可以实现当一个Activity完全加载完毕后,然后就执行,有点像js里面的window.onload=function()
	 */
	/*@Override
	public void onWindowFocusChanged(boolean hasFocus) {
		// TODO Auto-generated method stub
		mAnimation.start(); 
		super.onWindowFocusChanged(hasFocus);
	}*/
}
来看MainActivity里面的代码:

package com.example.progressdialogdemo;

import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;

/**
 * 
 * @author easy
 * 博客地址:http://blog.youkuaiyun.com/gameleague
 */
public class MainActivity extends Activity {
	private Boolean isNetError=true;
	/** 模拟获取返回的 **/
	private String canshu1;
	/** 这是你的进度条 **/
	private CustomProgressDialog dialog;
	/** 这是用于登录成功之后的事件 这里是在本界面显示登录返回的信息 **/
	private TextView textView1;
	private Button button1;
	/** 这是模拟服务器返回登录后的参数,例如json **/
	private EditText editText1;
	/** new 一个 Handler,这里是要写在onCreate前面 **/
	Handler loginHandler = new Handler() {
		//得到传递过来的message
		public void handleMessage(Message msg) {
			isNetError = msg.getData().getBoolean("isNetError");
			canshu1 = msg.getData().getString("canshu1");
			
			if (isNetError&&canshu1.equals("admin")) {
				Toast.makeText(MainActivity.this, "登录成功:admin",
						Toast.LENGTH_SHORT).show();
				textView1.invalidate();
				textView1.setText("登录成功:admin");
			}else{
				Toast.makeText(MainActivity.this, "出错了,请输入admin",
						Toast.LENGTH_SHORT).show();
				textView1.invalidate();
				textView1.setText("登录出错了");
			}
			
		}
	};
	
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        editText1 = (EditText) findViewById(R.id.editText1);
        textView1 = (TextView) findViewById(R.id.textView1);
        button1 = (Button) findViewById(R.id.button1);
        button1.setOnClickListener(new OnClickListener(){

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				//调用 LoginDialog 方法
				 LoginDialog();
			}
        	
        });
       
    }
    /** 进度条,自己可以定义 **/
	private void LoginDialog() {
		//可以新建不同图片像anim文件夹下的frame文件,随意更换,以达到整个应用公用此方法的目的。
		dialog =new CustomProgressDialog(this, "正在加载中...",R.anim.frame);
		dialog.show();
		// 开一个线程进行登录验证
		thread();
		
	}
	/*
     * 调用公共线程方法
     */
    public void thread(){
    	Thread hideview = new Thread(new LoginFailureHandler());
		hideview.start();
    }
	/** 登录时调用的Runnable **/
    public class LoginFailureHandler implements Runnable {

    	@Override
		public void run() {
    		//这里模拟登录时间延时,可换成登录请求验证什么的
    		try {
    	        Thread.sleep(5000);//括号里面的5000代表5000毫秒,也就是5秒,可以该成你需要的时间
    	        canshu1 = editText1.getText().toString();
    		} catch (InterruptedException e) {
    	        e.printStackTrace();
    		}
    		//这里写获取到参数之后东西并存在Bundle里面
    		if(isNetError){
			Message message = new Message();
			Bundle bundle = new Bundle();
			bundle.putBoolean("isNetError", isNetError);
			bundle.putString("canshu1", canshu1);
			//封装到message里面给Handler发送过去
			message.setData(bundle);
			loginHandler.sendMessage(message);
			//loginHandler处理完毕取消进度条
			dialog.dismiss();
		}
		}
    }
}

注释解释的很清楚了,这里不再阐述,把上一篇看懂,再看这一篇一点也不难

看效果图



       源码下载点这里,不要分。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值