前段時間,做了一個android塗鴉板項目(http://mm.10086.cn/1007/300001153536.html?fw=411130 ),在項目中,用到了一些自定義的對話框,如圖所示。
在參考了android提供的ApiDemos程序以後,這裏對如何實現自己定義的對話框進行一下總結。
在android 的ApiDemos中的com.example.android.apis.graphics包下,有一個ColorPickerDialog類,是經典 的自定義對話框的例子,我們在去除一些代碼,剩下的主框架代碼如下(代碼中的註釋詳細註明每個類和方法的用途):
public class ColorPickerDialog extends Dialog {
/**
* 監聽接口,通過此接口,可以把自定義Dialog需要向外界傳遞的信息,傳遞出去
*/
public interface OnColorChangedListener {
void colorChanged(int color);
}
/**
* 需要在對話框(ColorPickerDialog)上呈現的視圖,我們自定義對話框的工作,主要就是構造出一個這樣的視圖
*/
private static class ColorPickerView extends View {
private OnColorChangedListener mListener;
/**
* ColorPickerView的構造函數,可以在這個構造函數裏用android自帶的控件,比如說LinearLayout、EditText和SeekBar等,把ColorPickerView構造出來。
* 也可以在onDraw(Canvas canvas)函數中,把ColorPickerView給繪製出來,ColorPickerView採用的就是這種方法。
*/
ColorPickerView(Context c, OnColorChangedListener l, int color) {
super(c);
}
/**
* 在這個函數裏把ColorPickerView給繪製出來
* @param canvas
*/
@Override
protected void onDraw(Canvas canvas) {
}
/**
* 通過此方法來設置ColorPickerView的寬度和高度
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(CENTER_X*2, CENTER_Y*2);
}
/**
* 在這個函數裏,調用監聽接口OnColorChangedListener的方法,把此自定義Dialog需要向外界傳遞的信息設置進去
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
mListener.colorChanged(mCenterPaint.getColor());//這條語句調用了監聽接口的方法,把信息設置了進去
}
return true;
}
}
/**
* 自定義對話框的構造方法
*/
public ColorPickerDialog(Context context,
OnColorChangedListener listener,
int initialColor) {
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OnColorChangedListener l = new OnColorChangedListener() {
public void colorChanged(int color) {
mListener.colorChanged(color);
dismiss();
}
};
/**
* 只要通過ColorPickerDialog的setContentView方法,即可把我們辛苦繪製的ColorPickerView視圖在對話框上呈現出來。
*/
setContentView(new ColorPickerView(getContext(), l, mInitialColor));
setTitle("Pick a Color");//這條語句設置對話框的標題
}
}
總的來說,創建自定義Dialog的關鍵只有兩個步驟:
1.創建一個需要在自定義Dialog顯示的自定義View,創建這個自定義View時,既可以在這個View的構造方法中用android自帶的控件把 自定義View構造出來;也可以在自定義View的@Override protected void onDraw(Canvas canvas)方法中,把自定義View繪製出來
2.在自定義Dialog的@Override protected void onCreate(Bundle savedInstanceState)方法中,通過setContentView(自定義View);方法,把我們的自定義View顯示出來
在創建好自定義Dialog後,我們在別的類中,只要調用自定義Dialog的構造函數就可以把自定義Dialog顯示出來。對於 ColorPickerDialog這個類,調用語句如下:new ColorPickerDialog(getContext(), listener, mPaint.getColor()).show();
下面提供一個在自定義View的構造函數中把View構造出來的例子:
/**
* 文字對話框
*/
public class TextDialog extends Dialog implements SeekBar.OnSeekBarChangeListener{
private LinearLayout linearLayout;
private EditText etForText;
private SeekBar seekBar;
private TextView tvForSeekBar;
private Button btnOk;
private Button btnCancel;
private LinearLayout topChildLinearLayout;
private LinearLayout bottomChildLinearLayout;
private OnTextInputListener mListener;
/**
* 文字對話框標題
*/
private String title = "請輸入文字與選擇文字大小";
public interface OnTextInputListener {
void textInput(String text, int textSize);
}
public TextDialog(Context context, OnTextInputListener listener)
{
super(context);
mListener = listener;
linearLayout = new LinearLayout(getContext());
linearLayout.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
linearLayout.setOrientation(LinearLayout.VERTICAL);
linearLayout.setGravity(Gravity.CENTER);
etForText = new EditText(context);
etForText.setMinLines(5);//設置最大行數
seekBar = new SeekBar(context);
seekBar.setLayoutParams(new LinearLayout.LayoutParams(200, LayoutParams.FILL_PARENT));
seekBar.setMax(100);
seekBar.setProgress(50);
seekBar.setOnSeekBarChangeListener(this);
tvForSeekBar = new TextView(context);
tvForSeekBar.setText("50");
btnOk = new Button(getContext());
btnOk.setText("確定");
btnCancel = new Button(getContext());
btnCancel.setText("取消");
linearLayout.addView(etForText);
topChildLinearLayout = new LinearLayout(getContext());
topChildLinearLayout.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
topChildLinearLayout.setOrientation(LinearLayout.HORIZONTAL);
topChildLinearLayout.addView(seekBar);
topChildLinearLayout.addView(tvForSeekBar);
linearLayout.addView(topChildLinearLayout);
bottomChildLinearLayout = new LinearLayout(getContext());
bottomChildLinearLayout.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
bottomChildLinearLayout.setOrientation(LinearLayout.HORIZONTAL);
bottomChildLinearLayout.setGravity(Gravity.CENTER);
bottomChildLinearLayout.addView(btnOk);
bottomChildLinearLayout.addView(btnCancel);
linearLayout.addView(bottomChildLinearLayout);
btnOk.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
// TODO Auto-generated method stub
//驗證text是否爲空
String text = etForText.getText().toString()/*.replace("/n", "")*/;
if(text == null || text.trim().equals(""))
{
Toast.makeText(getContext(), "文字不能爲空", Toast.LENGTH_SHORT).show();
return;
}
int textSizeInt = Integer.valueOf(tvForSeekBar.getText().toString());
mListener.textInput(text, textSizeInt);
dismissDialog();
}
});
btnCancel.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
// TODO Auto-generated method stub
dismissDialog();
}
});
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(linearLayout);
setTitle(title);
}
public void dismissDialog()
{
this.dismiss();
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
{
// TODO Auto-generated method stub
tvForSeekBar.setText(progress + "");
}
@Override
public void onStartTrackingTouch(SeekBar seekBar)
{
// TODO Auto-generated method stub
}
@Override
public void onStopTrackingTouch(SeekBar seekBar)
{
// TODO Auto-generated method stub
}
}
此自定義Dialog的效果圖如下:
全文結束,謝謝大家。
說到對話框你肯定會想到AlertDialog.Builder。當然這次不是用AlertDialog.Builder來實現的!而是Dialog類
AlertDialog.Builder提供的方法有:
setTitle():給對話框設置title.
setIcon():給對話框設置圖標。
setMessage():設置對話框的提示信息
setItems():設置對話框要顯示的一個list,一般用於要顯示幾個命令時
setSingleChoiceItems():設置對話框顯示一個單選的List
setMultiChoiceItems():用來設置對話框顯示一系列的複選框。
setPositiveButton():給對話框添加”Yes”按鈕。
setNegativeButton():給對話框添加”No”按鈕。
那麼在Dialog類怎樣實現的呢?當然是layout啦,你可以自定義一個xml來佈置你對話框
看看例子和源碼吧
package com.hl;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
public class MyDialog extends Activity implements android.view.View.OnClickListener {
Button btn1=null;
Button btn2=null;
Button btn3=null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn1=(Button)findViewById(R.id.b1);
btn2=(Button)findViewById(R.id.b2);
btn3=(Button)findViewById(R.id.b3);
btn1.setOnClickListener(this);
btn2.setOnClickListener(this);
btn3.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch(v.getId()){
case R.id.b1:
break;
case R.id.b2:
case R.id.b3:
new MyDialogs(this).setDisplay();
break;
default:
}
}
class MyDialogs extends Dialog implements android.view.View.OnClickListener{
private Button b1;
private Window window=null;
public MyDialogs(Context context){
super(context);
}
public void setDisplay(){
setContentView(R.layout.dialog);//設置對話框的佈局
b1=(Button)findViewById(R.id.clo);
b1.setOnClickListener(this);
setProperty();
setTitle("自定義對話框");//設定對話框的標題
show();//顯示對話框
}
//要顯示這個對話框,只要創建該類對象.然後調用該函數即可.
public void setProperty(){
window=getWindow();// 得到對話框的窗口.
WindowManager.LayoutParams wl = window.getAttributes();
wl.x =0;//這兩句設置了對話框的位置.0爲中間
wl.y =180;
wl.alpha=0.6f;//這句設置了對話框的透明度
wl.gravity=Gravity.BOTTOM;
window.setAttributes(wl);
}
@Override
public void onClick(View v) {
dismiss();//取消
}
}
}
附件下載:
MyDialog.rar 40.76KB
自定義Android對話框的顯示位置
系統中所有對話框,默認佈局方式都是居中顯示,如果想自定義顯示位置可以考慮如下方式:
- ……
- Window mWindow = dialog.getWindow();
- WindowManager.LayoutParams lp = mWindow.getAttributes();
- lp.x= xxx;
- lp.y= xxx;
缺省居中lp.x=0,lp.y=0
新座標 x小於0左移,大於0右移;y小於0上移,大於0下移
- @Override
- protected void onDestroy() {
- super.onDestroy();
- android.os.Process.killProcess(android.os.Process.myPid());
- }
- public static String wrap(String str, int wrapLength, String newLineStr, boolean wrapLongWords) {
- if (str == null) {
- return null;
- }
- if (newLineStr == null) {
- newLineStr = System.getProperty("line.separator");
- }
- if (wrapLength < 1) {
- wrapLength = 1;
- }
- int inputLineLength = str.length();
- int offset = 0;
- StringBuffer wrappedLine = new StringBuffer(inputLineLength + 32);
- while ((inputLineLength - offset) > wrapLength) {
- if (str.charAt(offset) == ' ') {
- offset++;
- continue;
- }
- int spaceToWrapAt = str.lastIndexOf(' ', wrapLength + offset);
- if (spaceToWrapAt >= offset) {
- // normal case
- wrappedLine.append(str.substring(offset, spaceToWrapAt));
- wrappedLine.append(newLineStr);
- offset = spaceToWrapAt + 1;
- } else {
- // really long word or URL
- if (wrapLongWords) {
- // wrap really long word one line at a time
- wrappedLine.append(str.substring(offset, wrapLength + offset));
- wrappedLine.append(newLineStr);
- offset += wrapLength;
- } else {
- // do not wrap really long word, just extend beyond limit
- spaceToWrapAt = str.indexOf(' ', wrapLength + offset);
- if (spaceToWrapAt >= 0) {
- wrappedLine.append(str.substring(offset, spaceToWrapAt));
- wrappedLine.append(newLineStr);
- offset = spaceToWrapAt + 1;
- } else {
- wrappedLine.append(str.substring(offset));
- offset = inputLineLength;
- }
- }
- }
- }
- // Whatever is left in line is short enough to just pass through
- wrappedLine.append(str.substring(offset));
- return wrappedLine.toString();
- }
Android自定義對話框(Dialog)
實現的效果是:
“長按圖標可移動位置或刪除
下次不再提示
確定 取消
Acitivity
01 |
LayoutInflater inflater = LayoutInflater.from( this
); |
02 |
checkView = inflater.inflate(R.layout.dialog, null ); |
03 |
04 |
//實例化複選框 |
05 |
cb = (CheckBox)checkView.findViewById(R.id.cb1); |
06 |
//對複選框設置事件監聽 |
07 |
cb.setOnCheckedChangeListener( new
CheckBox.OnCheckedChangeListener(){ |
08 |
@Override |
09 |
public void onCheckedChanged(CompoundButton arg0, boolean
arg1) { |
10 |
if (cb.isChecked()){ |
11 |
//設置爲不顯示提示 |
12 |
editor.putBoolean( "showMoveTip"
, false ); |
13 |
} |
14 |
else { |
15 |
//設置爲顯示提示 |
16 |
editor.putBoolean( "showMoveTip"
, true ); |
17 |
} |
18 |
} |
19 |
}); |
20 |
21 |
final AlertDialog dialog=
new AlertDialog.Builder(
this ) |
22 |
.setTitle( "提示" ) |
23 |
.setView(checkView) |
24 |
.setPositiveButton( "確定" , new DialogInterface.OnClickListener() { |
25 |
@Override |
26 |
public void onClick(DialogInterface dialog, int which) { |
27 |
editor.commit(); |
28 |
} |
29 |
}) |
30 |
.setNegativeButton( "取消" , new DialogInterface.OnClickListener() { |
31 |
@Override |
32 |
public void onClick(DialogInterface dialog, int which) { |
33 |
34 |
} |
35 |
}).create(); |
36 |
dialog.show(); |