android自定义透明对话框,透明提示框,自定义Dialog

本文介绍了如何在Android中自定义透明对话框和提示框,避免使用第三方库,通过简单的代码实现类似效果。作者分享了一个包含动画效果的自定义Dialog的实践过程,并提供了相关代码示例。

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

  昨天在上网无意间发现一个android自定义透明的对话框,看着效果挺不错。于是研究了下。结果是一个第三方的库文件。犹豫了,这个效果虽然看着还不错,但是为了这一个功能引用一个库,觉得有点小题大做。于是乎再深研究发现原来这个库里面就只有两个类,作为一个项目需要引用库的话,如果只有两个类不知道其他程序员们怎么想,反正我是不会为两个类去专门引用一个库,一翻整理后,把这个直接集成到项目里,写了个demo给大家分享:

效果图


      首先写之前需要做些准备工作:

     一,在res下新建anim文件夹添加一个progressbar.xml文件


<span style="font-size:24px;"><?xml version="1.0" encoding="utf-8"?> 
<set android:shareInterpolator="false" xmlns:android="http://schemas.android.com/apk/res/android"> 
<rotate 
android:interpolator="@android:anim/linear_interpolator" 
android:pivotX="50%" 
android:pivotY="50%" 
android:fromDegrees="0" 
android:toDegrees="+360" 
android:duration="1500" 
android:startOffset="-1" 
android:repeatMode="restart" 
android:repeatCount="-1"/>
</set></span>
    二,在drawble文件夹下添加一个transparent_bg.xml文件

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="#aa000000" />
    <corners android:radius="10dp" />
</shape>
  三,在values下的styles.xml中添加一个自定义的样式,将来引用

  <style name="Transparent" parent="@android:style/Theme.Dialog">
        <item name="android:windowFrame">@null</item>
        <item name="android:windowIsFloating">true</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
        <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
        <item name="android:windowBackground">@drawable/transparent_bg</item>
        <item name="android:windowNoTitle">true</item>
    </style>

好了,准备工作就绪。

下来看代码

新建一个

TransparentDialog类继承Dialog
public TransparentDialog(Context context, int theme) {
		super(context, theme);
	}
	
	public static TransparentDialog createDialog(Context context) {
		TransparentDialog dialog = new TransparentDialog(context, R.style.Transparent);
		dialog.setContentView(R.layout.transparent);
		dialog.getWindow().getAttributes().gravity = Gravity.CENTER;
		return dialog;
	}

	public void setMessage(String message) {
		TextView msgView = (TextView)findViewById(R.id.transparent_message);
		msgView.setText(message);
	}
	
	public void setImage(Context ctx, int resId) {
		ImageView image = (ImageView)findViewById(R.id.transparent_image);
		image.setImageResource(resId);
		
		if(resId==R.drawable.transparent_spinner) {
			Animation anim = AnimationUtils.loadAnimation(ctx,R.anim.progressbar);
			anim.start();
			image.startAnimation(anim);
		}

	}

里面的findviewbyid的控件是在布局文件transparent.xml里面,很简单就一张图片和一个文本,布局如下

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_margin="16dp"
    android:layout_width="200dp"
    android:layout_height="wrap_content" >

    <ImageView 
        android:id="@+id/transparent_image"
        android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:layout_gravity="center"
		android:contentDescription="@string/app_name"/>

	<TextView 
    	android:id="@+id/transparent_message"
    	android:layout_width="match_parent"
    	android:layout_height="wrap_content"
    	android:textSize="16sp"
    	android:layout_marginTop="10dp" />

</LinearLayout>
然后在新建一个 Transparent类,用于自定义对话框的属性和样式,很简单,每种对话框对应一个方法

public static void showLoadingMessage(Context context, String msg, boolean cancelable) {
   dismiss();
   setDialog(context, msg, R.drawable.transparent_spinner, cancelable);
   if(dialog!=null) dialog.show();

}

这个方法就是夹在时候显示的对话框消息,其余几个类似。
其中
dialog.setCancelable(cancelable);方法接收一个布尔值,表示当按下手机back按键时候,对话框是否会消失。
setDialog()可以在里面设置弹出对话框的文字和图片
dismissAfter2s()方法用于关闭对话框,提示消息弹出2秒后关闭,这里我们起了一个线程,用handler发送一个消息,
当接收到消息时候,调用<span style="background-color: rgb(255, 255, 255); font-family: Consolas; font-size: 12.8pt;">dismiss()方法关闭对话框</span>
正在加载中的弹出框有点特殊,因为我们有时候不知道要加载多久,所以它会一直存在,当我们按下back按键时候会关闭
</pre>
public static void showErrorMessage(Context context, String msg) {
		dismiss();
		setDialog(context, msg, R.drawable.transparent_error, true);
		if(dialog!=null) {
			dialog.show();
			dismissAfter2s();
		}
	}

	public static void showSuccessMessage(Context context, String msg) {
		dismiss();
		setDialog(context, msg, R.drawable.transparent_success, true);
		if(dialog!=null) {
			dialog.show();
			dismissAfter2s();
		}
	}
	
	public static void showInfoMessage(Context context, String msg) {
		dismiss();
		setDialog(context, msg, R.drawable.transparent_info, true);
		if(dialog!=null) {
			dialog.show();
			dismissAfter2s();
		}
	}
	

	
	private static void setDialog(Context ctx, String msg, int resId, boolean cancelable) {
		context = ctx;

		if(!isContextValid()){
			return;
		}
		dialog = TransparentDialog.createDialog(ctx);
		dialog.setMessage(msg);
		dialog.setImage(ctx, resId);
		dialog.setCanceledOnTouchOutside(false);
		dialog.setCancelable(cancelable);		// back键是否可dimiss对话框
		

	}

	/**
	 * 关闭对话框
	 */
	public static void dismiss() {
		if(isContextValid() && dialog!=null && dialog.isShowing())
			dialog.dismiss();
		dialog = null;
	}


	/**
	 * 计时关闭对话框
	 * 
	 */
	private static void dismissAfter2s() {
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					Thread.sleep(2000);
					handler.sendEmptyMessage(0);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}).start();
	}
	

	private static Handler handler = new Handler() {
		public void handleMessage(Message msg) {
			if(msg.what==0)
				dismiss();
		};
	};
	

	/**
	 * 判断parent view是否还存在
	 * 若不存在不能调用dismis,或setDialog等方法
	 * @return
	 */
	private static boolean isContextValid() {
		if(context==null)
			return false;
		if(context instanceof Activity) {
			Activity act = (Activity)context;
			if(act.isFinishing())
				return false;
		}
		return true;
	}

接下来就是在代码中直接调用了,这里不作过多解释,直接看源码,相信聪明的你肯定可以看懂
public class MainActivity extends Activity implements View.OnClickListener {

    private Button LoadingBt;
    private Button ErrorBt;
    private Button SuccessgBt;
    private Button ShowMessageBt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

       
        LoadingBt = (Button) findViewById(R.id.bt_loading);
        ErrorBt = (Button) findViewById(R.id.bt_error);
        SuccessgBt = (Button) findViewById(R.id.bt_success);
        ShowMessageBt = (Button) findViewById(R.id.bt_show_message);
        LoadingBt.setOnClickListener(this);
        ErrorBt.setOnClickListener(this);
        SuccessgBt.setOnClickListener(this);
        ShowMessageBt.setOnClickListener(this);

      




    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.bt_loading:
                Transparent.showLoadingMessage(this,"加载中",true);
                break;
            case R.id.bt_error:
                Transparent.showErrorMessage(this,"加载错误");
                break;
            case R.id.bt_success:
                Transparent.showSuccessMessage(this,"加载成功");
                break;
            case R.id.bt_show_message:
                Transparent.showInfoMessage(this,"显示信息");
                break;
        }
    }



}
说明:

1. 隐藏提示框


在调用新的show之前,Transparent会自动关闭正在显示的。也可以使用
<span style="color:#ff0000;">Transparent<span style="background-color: rgb(255, 255, 255); font-family: Consolas; font-size: 12px;">.dismiss(); 方法手动关闭。</span></span>


2. 替换icon


四个图标在drawable文件夹内,使用相同名字图标替换即可。

好了,就是这么简单。最后附上效果图和源码


透明对话框 void TransparentBlt( HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HBITMAP hBitmap, int nXSrc, int nYSrc, COLORREF colorTransparent, HPALETTE hPal ) { CDC dc, memDC, maskDC, tempDC; dc.Attach( hdcDest ); maskDC.CreateCompatibleDC(&dc); CBitmap maskBitmap; //add these to store return of SelectObject() calls CBitmap* pOldMemBmp = NULL; CBitmap* pOldMaskBmp = NULL; HBITMAP hOldTempBmp = NULL; memDC.CreateCompatibleDC(&dc); tempDC.CreateCompatibleDC(&dc); CBitmap bmpImage; bmpImage.CreateCompatibleBitmap( &dc, nWidth, nHeight ); pOldMemBmp = memDC.SelectObject( &bmpImage ); // Select and realize the palette if( dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE && hPal ) { ::SelectPalette( dc, hPal, FALSE ); dc.RealizePalette(); ::SelectPalette( memDC, hPal, FALSE ); } hOldTempBmp = (HBITMAP) ::SelectObject( tempDC.m_hDC, hBitmap ); memDC.BitBlt( 0,0,nWidth, nHeight, &tempDC, nXSrc, nYSrc, SRCCOPY ); // Create monochrome bitmap for the mask maskBitmap.CreateBitmap( nWidth, nHeight, 1, 1, NULL ); pOldMaskBmp = maskDC.SelectObject( &maskBitmap ); memDC.SetBkColor( colorTransparent ); // Create the mask from the memory DC maskDC.BitBlt( 0, 0, nWidth, nHeight, &memDC, 0, 0, SRCCOPY ); // Set the background in memDC to black. Using SRCPAINT with black // and any other color results in the other color, thus making // black the transparent color memDC.SetBkColor(RGB(0,0,0)); memDC.SetTextColor(RGB(255,255,255)); memDC.BitBlt(0, 0, nWidth, nHeight, &maskDC, 0, 0, SRCAND); // Set the foreground to black. See comment above. dc.SetBkColor(RGB(255,255,255)); dc.SetTextColor(RGB(0,0,0)); dc.BitBlt(nXDest, nYDest, nWidth, nHeight, &maskDC, 0, 0, SRCAND); // Combine the foreground with the background dc.BitBlt(nXDest, nYDest, nWidth, nHeight, &memDC, 0, 0, SRCPAINT); if (hOldTempBmp) ::SelectObject( tempDC.m_hDC, hOldTempBmp); if (pOldMaskBmp) maskDC.SelectObject( pOldMaskBmp ); if (pOldMemBmp) memDC.SelectObject( pOldMemBmp ); dc.Detach(); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值