自定義Dialog
效果圖:
核心代碼:
package com.zms.toast;
import android.app.Dialog;
import android.content.Context;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Message;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView;
import java.util.Random;
/**
* Created by AlexZhou on 2015/3/2.
* 14:51
*/
public class CustomDialog extends Dialog {
private static int defaultWidth = 200;
private static int defaultHeight = 160;
private int progress = 0;
private TextView dialogText;
public CustomDialog(Context context) {
super(context);
}
public CustomDialog(Context context, int layout, int style) {
this(context, defaultWidth, defaultHeight, layout, style);
}
public float getDensity(Context context) {
Resources res = context.getResources();
DisplayMetrics dm = res.getDisplayMetrics();
return dm.density;
}
public CustomDialog(Context context, int width, int height, int layout, int style) {
super(context, style);
// 設定内容
setContentView(layout);
// 設定視窗屬性
Window window = getWindow();
WindowManager.LayoutParams params = window.getAttributes();
// 設定寬度、高度、密度、對齊方式
float density = getDensity(context);
params.width = (int) (width * density);
params.height = (int) (height * density);
params.gravity = Gravity.CENTER;
window.setAttributes(params);
dialogText = (TextView) findViewById(R.id.dialogText);
new Thread(new TimeThread()).start();
}
final Handler timeHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
if (progress < 100) {
progress = progress + new Random().nextInt(10);
if (progress <= 100) {
dialogText.setText("更新進度" + progress + "%");
} else {
dialogText.setText("更新進度100%");
}
} else {
dialogText.setText("更新完成");
dismiss();
}
}
super.handleMessage(msg);
}
};
public class TimeThread implements Runnable {
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
Message message = new Message();
message.what = 1;
timeHandler.sendMessage(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@Override
public void dismiss() {
super.dismiss();
}
}
自定義Toast和Notification
文章末尾有代碼連結,首先貼個效果圖,下拉通知裡面的是Notification,居中的是自定義的Toast:
主函數的布局檔案隻有兩個按鈕,分别是Toast和Notification:
<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:background="@drawable/new_wallpaper_final_full_size02a"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.mytoast.Main" >
<Button
android:id="@+id/btn_toast"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Toast" />
<Button
android:id="@+id/btn_notify"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/btn_toast"
android:text="Notification" />
</RelativeLayout>
自定義Toast布局檔案:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toast_ll_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#30000000"
android:orientation="vertical"
android:padding="20dp" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@drawable/ic_launcher" />
<TextView
android:id="@+id/toast_tv"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#0000ff"
android:textSize="25dp" />
</LinearLayout>
<TextView
android:id="@+id/toast_time"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#0000ff"
android:textSize="25dp" />
</LinearLayout>
綁定監聽器:
btn_toast = (Button) findViewById(R.id.btn_toast);
btn_notify = (Button) findViewById(R.id.btn_notify);
btn_toast.setOnClickListener(new onClickListenerImp());
btn_notify.setOnClickListener(new onClickListenerImp());
核心内容都在監聽函數裡了:
private class onClickListenerImp implements OnClickListener {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (v == btn_toast) {
LayoutInflater inflater = LayoutInflater.from(Main.this);
View myView = inflater.inflate(R.layout.mytoast,
(ViewGroup) findViewById(R.id.toast_ll_main));
TextView toast_tv = (TextView) myView
.findViewById(R.id.toast_tv);
TextView toast_time = (TextView) myView
.findViewById(R.id.toast_time);
SpannableString spannableString = new SpannableString(
"Hello,Android! -zhoumushui");
spannableString.setSpan(new ForegroundColorSpan(Color.YELLOW),
0, 14, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(new ForegroundColorSpan(Color.CYAN),
14, spannableString.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
toast_tv.setText(spannableString);
// SimpleDateFormat sdf = new
// SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
SimpleDateFormat sdf = new SimpleDateFormat(
"yyyy年MM月dd日 HH:mm:ss:SSS");
toast_time.setText(sdf.format(new Date()));
Toast myToast = new Toast(Main.this);
myToast.setDuration(Toast.LENGTH_SHORT);
myToast.setView(myView);
myToast.setGravity(Gravity.CENTER, 0, 0);
myToast.show();
} else if (v == btn_notify) {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(
R.drawable.ic_launcher, "Hello,Android!--zhoumushui",
System.currentTimeMillis());
notification.flags = Notification.FLAG_AUTO_CANCEL;
Intent intent = new Intent(Main.this, AfterClickNotify.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent contentIntent = PendingIntent
.getActivity(Main.this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
notification.setLatestEventInfo(Main.this, "Hello,Android!",
"zhoumushui.", contentIntent);
notificationManager.notify(R.string.app_name, notification);
}
}
}
有于隻是示範,點選Notification後跳轉到的Activity隻是定義了布局,沒做複雜處理:
public class AfterClickNotify extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.afterclicknotify);
}
}
布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#300000ff"
android:text="Hello Android\nZhou Mu Shui\nblog.csdn.net/zhoumushui"
android:textSize="25dp" />
</LinearLayout>
好了,今天的内容比較基礎,就先這樣了,改日再寫資料存儲的内容。
代碼工程下載下傳
自定義PopupWindow:
效果圖如下,類似iOS的ActionSheet:
核心代碼:
package com.zms.actionsheet;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface.OnCancelListener;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
public class ActionSheet {
public interface OnActionSheetSelected {
void onClick(int whichButton);
}
private ActionSheet() {
}
public static Dialog showSheet(Context context, final OnActionSheetSelected actionSheetSelected,
OnCancelListener cancelListener) {
final Dialog dlg = new Dialog(context, R.style.ActionSheet);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout layout = (LinearLayout) inflater.inflate(R.layout.actionsheet, null);
final int cFullFillWidth = 10000;
layout.setMinimumWidth(cFullFillWidth);
TextView mContent = (TextView) layout.findViewById(R.id.content);
TextView mCancel = (TextView) layout.findViewById(R.id.cancel);
mContent.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
actionSheetSelected.onClick(0);
dlg.dismiss();
}
});
mCancel.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
actionSheetSelected.onClick(1);
dlg.dismiss();
}
});
Window w = dlg.getWindow();
WindowManager.LayoutParams lp = w.getAttributes();
lp.x = 0;
final int cMakeBottom = -1000;
lp.y = cMakeBottom;
lp.gravity = Gravity.BOTTOM;
dlg.onWindowAttributesChanged(lp);
dlg.setCanceledOnTouchOutside(false);
if (cancelListener != null)
dlg.setOnCancelListener(cancelListener);
dlg.setContentView(layout);
dlg.show();
return dlg;
}
}
仿微信電話本短信标題的PopupWindow
剛剛看了部電影《Rush》,作為F1迷很是喜歡這種feel,讓我想起了Ayrton Senna的那個年代,遺憾的是一味追求速度,難免會有悲劇伴随。
好了,步入正題。
在項目中我不是用PopupWindwow實作的,當時我的做法是利用布局的可見性,結合代碼設定,雖然實作了同樣效果,但是比較麻煩,并且不便于後期維護。
最近寫了個小Demo,發現用PopupWindow實作友善很多,今天總結一下:
布局檔案有兩個:主檔案布局main.xml和對應的popwindow.xml,布局都比較簡單,也沒有美化。主要邏輯都在代碼裡。
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffff"
android:orientation="vertical" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="50dp"
android:background="#454545"
android:orientation="horizontal"
android:weightSum="5" >
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@null"
android:src="@drawable/icon" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_weight="3"
android:onClick="ShowOrHidePopup"
android:weightSum="3" >
<TextView
android:id="@+id/tv_topbar"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center"
android:text="短信"
android:textSize="20dp" />
</LinearLayout>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@null"
android:src="@drawable/icon" />
</LinearLayout>
popwindow.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#454545"
android:orientation="vertical" >
<View
android:layout_width="fill_parent"
android:layout_height="1px"
android:background="#000000" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="90dp"
android:orientation="horizontal" >
<TextView
android:layout_width="wrap_content"
android:layout_height="90dp"
android:drawableTop="@drawable/icon"
android:layout_weight="1"
android:gravity="center"
android:text="收藏短信"
/>
<View
android:layout_width="1px"
android:layout_height="95dp"
android:layout_gravity="center_vertical"
android:background="#000000"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="90dp"
android:drawableTop="@drawable/icon"
android:layout_weight="1"
android:gravity="center"
android:text="廣告垃圾"
/>
</LinearLayout>
</LinearLayout>
代碼也不長,很友善使用的一個控件。主要就是用一個LayoutInflater把popwindow.xml加載到一個View中,然後用PopWindow的對象加載這個View,并且設定layout樣式,剩下的沒什麼差別了。
package com.example.popupwindow;
import android.app.Activity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.WindowManager.LayoutParams;
import android.widget.Button;
import android.widget.PopupWindow;
import android.widget.RadioGroup;
import android.widget.TextView;
public class MyPopupWindowDemo extends Activity {
private Button popbut = null; // 呼出狀态Button
private RadioGroup changestatus = null; //
private TextView statusinfo = null;
private Button cancel = null;
private PopupWindow popWin = null;
private View popView = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
super.setContentView(R.layout.main);
LayoutInflater inflater = LayoutInflater.from(this);
popView = inflater.inflate(R.layout.popwindow, null);
popWin = new PopupWindow(popView, LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT);
}
public void ShowOrHidePopup(View v) {
if (popWin.isShowing()) {
popWin.dismiss();
} else {
popWin.showAtLocation(v, Gravity.NO_GRAVITY, 0, 100);
}
}
}
ShowOrHide函數裡做了個判斷,isShowing是該PopWindow對象目前是否顯示,dismiss()函數就是把PopWindow給隐藏,showAtLocation則是在指定位置以指定Gravity顯示該PopWindow。這就是Android的便捷之處,什麼接口都是現成的,直接調用就行。當然,這隻是實作最基本的功能,想要更好的效果自然也得費點心思。
總覺得周末過得太快,還沒開始,就已經結束的感覺,一轉眼一天就沒了。
轉載請注明出處:周木水的CSDN部落格 http://blog.csdn.net/zhoumushui