Dialog相关

Dialog相关

自定义布局的Dialog

基类dialog

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import android.app.Activity;
import android.app.Dialog;

public abstract class BaseDialog extends Dialog implements
android.view.View.OnClickListener {
/**
* @param context
*/
protected Activity context;

public BaseDialog(Activity context) {
super(context, R.style.Dialog);
this.context = context;
getWindow().setBackgroundDrawableResource(android.R.color.transparent);
}

public BaseDialog(Activity context, String transparent) {//背景透明
super(context, R.style.Dialog_transparent);
this.context = context;
getWindow().setBackgroundDrawableResource(android.R.color.transparent);
}

public BaseDialog(Activity context, int resId) {
super(context, R.style.dialog_bottom);
this.context = context;
setContentView(resId);
}

public BaseDialog(Activity context, int resId, int styleId) {
super(context, styleId);
this.context = context;
setContentView(resId);
}

public void init() {
initView();
initData();
setListener();
}

public void initView() {
}


public void initData() {
}


public void setListener() {
}
}

style.xml中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<!--背景透明的弹窗风格-->
<style name="dialog_common" parent="@style/Dialog">
<item name="android:windowBackground">@android:color/transparent</item>
</style>

<style name="dialog_animation" parent="android:Animation">
<item name="android:windowEnterAnimation">@anim/dialog_enter</item>
<item name="android:windowExitAnimation">@anim/dialog_exit</item>
</style>

<style name="Dialog" parent="@android:style/Theme.Dialog">
<item name="android:windowFrame">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowContentOverlay">@null</item>
</style>
<style name="dialog_bottom" parent="@style/dialog_common">
<item name="android:windowNoTitle">true</item>
<item name="android:windowAnimationStyle">@style/dialog_animation</item>
<item name="android:windowContentOverlay">@null</item>
</style>
<style name="Dialog_transparent" parent="@android:style/Theme.Dialog">
<item name="android:windowFrame">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowBackground">@color/transparent</item>
<item name="android:backgroundDimEnabled">false</item>
</style>



<style name="PopupAnimation" mce_bogus="1" parent="android:Animation">
<item name="android:windowEnterAnimation">@anim/push_in_style</item>
<item name="android:windowExitAnimation">@anim/push_out_style</item>
</style>

dialog_enter.xml

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

<translate
android:duration="400"
android:toYDelta="0%"
android:fillAfter="true"
android:fromYDelta="100%p" />

</set>

dialog_exit.xml

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

<translate
android:duration="400"
android:fromYDelta="0%"
android:fillAfter="true"
android:toYDelta="100%p" />

</set>

创建自己的dialog

image-20221025104747429

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public class FiltrateDataDialog extends BaseDialog{

private FiltrateDialogOnClick filtrateDialogOnClick;
private TextView oneItemTv;
private TextView twoItemTv;
private TextView threeItemTv;
private TextView cancelItemTv;

public FiltrateDataDialog(Activity context) {
//自定义的布局
super(context, R.layout.dialog_filtrate);

Window window = getWindow();
window.setWindowAnimations(R.style.PopupAnimation);
window.setGravity(Gravity.BOTTOM);
window.getDecorView().setPadding(0, 0, 0, 0);
WindowManager.LayoutParams lp = window.getAttributes();
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
window.setAttributes(lp);
init();
}

@Override
public void initView() {
super.initView();
oneItemTv = (TextView) findViewById(R.id.dialog_filtrate_total_tv);
twoItemTv = (TextView) findViewById(R.id.tv_issue_costomer);
threeItemTv = (TextView) findViewById(R.id.tv_issue_main);
cancelItemTv = (TextView) findViewById(R.id.tv_issue_diss);
oneItemTv.setOnClickListener(this);
twoItemTv.setOnClickListener(this);
threeItemTv.setOnClickListener(this);
cancelItemTv.setOnClickListener(this);
}

/**
* 提供对外的接口
*/
public interface FiltrateDialogOnClick{
void dialogOnClick(int state, FiltrateDataDialog dialog);
}

public void setFiltrateDialogOnClick(FiltrateDialogOnClick filtrateDialogOnClick){
this.filtrateDialogOnClick = filtrateDialogOnClick;
}

@Override
public void onClick(View v) {

}
}

dialog_filtrate.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?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="wrap_content">

<LinearLayout
android:id="@+id/ll_issue"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@color/white"
android:orientation="vertical">

<TextView
android:id="@+id/dialog_filtrate_total_tv"
android:layout_width="match_parent"
android:layout_height="39dp"
android:layout_marginLeft="14dp"
android:layout_marginRight="14dp"
android:layout_marginTop="20dp"
android:background="@drawable/dialog_picture_taker_normal_bg"
android:gravity="center"
android:text="历史总额"
android:textColor="#444"
android:textSize="15dp" />

<TextView
android:id="@+id/tv_issue_costomer"
android:layout_width="match_parent"
android:layout_height="39dp"
android:layout_marginLeft="14dp"
android:layout_marginRight="14dp"
android:layout_marginTop="15dp"
android:background="@drawable/dialog_picture_taker_normal_bg"
android:gravity="center"
android:text="最近30天"
android:textColor="#444"
android:textSize="15dp" />

<TextView
android:id="@+id/tv_issue_main"
android:layout_width="match_parent"
android:layout_height="39dp"
android:layout_marginLeft="14dp"
android:layout_marginRight="14dp"
android:layout_marginTop="15dp"
android:background="@drawable/dialog_picture_taker_normal_bg"
android:gravity="center"
android:text="最近7天"
android:textColor="#444"
android:textSize="15dp" />

<TextView
android:id="@+id/tv_issue_diss"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginBottom="14dp"
android:layout_marginLeft="14dp"
android:layout_marginRight="14dp"
android:layout_marginTop="15dp"
android:background="@drawable/issue_dialog_diss"
android:gravity="center"
android:text="取消"
android:textColor="#848484"
android:textSize="15dp" />
</LinearLayout>
</LinearLayout>

push_in_style.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

<translate
android:duration="300"
android:fromYDelta="0"
android:toYDelta="100%p" />

<alpha
android:duration="300"
android:fromAlpha="1.0"
android:toAlpha="0.5" />

</set>

push_out_style.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

<translate
android:duration="300"
android:fromYDelta="0"
android:toYDelta="100%p" />

<alpha
android:duration="300"
android:fromAlpha="1.0"
android:toAlpha="0.5" />

</set>

自定义布局的Dialog+选择日期Dialog

效果图

自定义布局弹窗.jpg

选择日期弹窗.jpg

工具

DateOrCityChooseLdy.java 基于WheelView的年月日选择器(城市选择器)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
package com.u1city.androidframe.Component.wheelview;

import android.app.Dialog;
import android.content.Context;
import android.content.res.AssetManager;
import android.text.format.Time;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

import com.u1city.androidframe.R;
import com.u1city.androidframe.common.system.DateUtil;
import com.u1city.module.common.Debug;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

/**
* @author linjy
* @time 2015-12-18 16:13:08
* 类说明:基于WheelView的年月日选择器(城市选择器)
*/
public class DateOrCityChooseLdy extends Dialog implements OnClickListener, OnWheelChangedListener {
/************* 日期选择 *****************/
private final Context context;
private final View contentView;
private int visibleItems = 7;
private WheelView yearWv;
private WheelView monthWv;
private WheelView dayWv;
public Button cancelBtn;
public TextView confirmBtn;
public TextView titleView;
private DateOrCityChooseListener dateChooseListener;
private String[] years;
private String[] months;
private String[] days;
int minYear = 1900;//选择日期的最小年 默认1940 //应燕谷坊要求修改最小年默认值为1900 by yangn
int maxMonth = 12;//选择日期的最大月份
private boolean isDatechoose;// 是否日期选择 否城市选择
private static final String TAG = "DateChooseLdy";

private boolean isToToday;// 日期是否只到当前日期
private int maxDay;//选择日期的最大日数

/************* 城市选择 *****************/
/**
* 所有省
*/
public String[] provinceDatas;
/**
* key - 省 value - 市
*/
public Map<String, String[]> citiesMap = new HashMap<String, String[]>();
/**
* key - 市 values - 区
*/
public Map<String, String[]> districsMap = new HashMap<String, String[]>();
/**
* key - 区 values - 邮编
*/
public Map<String, String> zipCodesMap = new HashMap<String, String>();

/**
* 当前省的名称
*/
public String currentProvince;
/**
* 当前市的名称
*/
public String currentCity;
/**
* 当前区的名称
*/
public String currentDistrict = "";

/**
* 当前区的邮政编码
*/
public String currentZipCode = "";
private ArrayWheelAdapter<String> yearAdapter;//年份apapter

public DateOrCityChooseLdy(Context context, final DateOrCityChooseListener dateChooseListener, boolean isDatechoose) {
super(context);
this.context = context;
this.dateChooseListener = dateChooseListener;
this.isDatechoose = isDatechoose;
/*** 注:这边共用城市选择的wheelView ***/
contentView = (ViewGroup) LayoutInflater.from(context).inflate(R.layout.layout_city_choose_ldy, null);
yearWv = (WheelView) contentView.findViewById(R.id.layout_city_choose_province_wv);
yearWv.addChangingListener(this);
monthWv = (WheelView) contentView.findViewById(R.id.layout_city_choose_city_wv);
monthWv.addChangingListener(this);
dayWv = (WheelView) contentView.findViewById(R.id.layout_city_choose_district_wv);
dayWv.addChangingListener(this);
yearWv.setShadowColor(0xf0f0f0, 0xf0f0f0, 0xf0f0f0);// 设置颜色
monthWv.setShadowColor(0xf0f0f0, 0xf0f0f0, 0xf0f0f0);
dayWv.setShadowColor(0xf0f0f0, 0xf0f0f0, 0xf0f0f0);
setVisibleItems(visibleItems);

cancelBtn = (Button) contentView.findViewById(R.id.layout_city_choose_cancel_btn);
confirmBtn = (Button) contentView.findViewById(R.id.layout_city_choose_confirm_btn);

cancelBtn.setOnClickListener(this);
confirmBtn.setOnClickListener(this);

titleView = (TextView) contentView.findViewById(R.id.layout_city_choose_title_tv);
setContentView(contentView);
initDates();
}

public DateOrCityChooseLdy(Context context, int style, final DateOrCityChooseListener dateChooseListener, boolean isDatechoose) {
super(context, style);
this.context = context;
this.dateChooseListener = dateChooseListener;
this.isDatechoose = isDatechoose;
contentView = (ViewGroup) LayoutInflater.from(context).inflate(R.layout.layout_city_choose_ldy, null);
yearWv = (WheelView) contentView.findViewById(R.id.layout_city_choose_province_wv);
yearWv.addChangingListener(this);
monthWv = (WheelView) contentView.findViewById(R.id.layout_city_choose_city_wv);
monthWv.addChangingListener(this);
dayWv = (WheelView) contentView.findViewById(R.id.layout_city_choose_district_wv);
dayWv.addChangingListener(this);
yearWv.setShadowColor(0xf0f0f0, 0xf0f0f0, 0xf0f0f0);// 设置颜色
monthWv.setShadowColor(0xf0f0f0, 0xf0f0f0, 0xf0f0f0);
dayWv.setShadowColor(0xf0f0f0, 0xf0f0f0, 0xf0f0f0);
setVisibleItems(visibleItems);
cancelBtn = (Button) contentView.findViewById(R.id.layout_city_choose_cancel_btn);
confirmBtn = (Button) contentView.findViewById(R.id.layout_city_choose_confirm_btn);
cancelBtn.setOnClickListener(this);
confirmBtn.setOnClickListener(this);
titleView = (TextView) contentView.findViewById(R.id.layout_city_choose_title_tv);
setContentView(contentView);

initDates();
}

public DateOrCityChooseLdy(Context context, int style, final DateOrCityChooseListener dateChooseListener, boolean isDatechoose, int minYear) {
super(context, style);
this.context = context;
this.dateChooseListener = dateChooseListener;
this.isDatechoose = isDatechoose;
this.minYear = minYear;
contentView = (ViewGroup) LayoutInflater.from(context).inflate(R.layout.layout_city_choose_ldy, null);
yearWv = (WheelView) contentView.findViewById(R.id.layout_city_choose_province_wv);
yearWv.addChangingListener(this);
monthWv = (WheelView) contentView.findViewById(R.id.layout_city_choose_city_wv);
monthWv.addChangingListener(this);
dayWv = (WheelView) contentView.findViewById(R.id.layout_city_choose_district_wv);
dayWv.addChangingListener(this);
yearWv.setShadowColor(0xf0f0f0, 0xf0f0f0, 0xf0f0f0);// 设置颜色
monthWv.setShadowColor(0xf0f0f0, 0xf0f0f0, 0xf0f0f0);
dayWv.setShadowColor(0xf0f0f0, 0xf0f0f0, 0xf0f0f0);
setVisibleItems(visibleItems);
cancelBtn = (Button) contentView.findViewById(R.id.layout_city_choose_cancel_btn);
confirmBtn = (TextView) contentView.findViewById(R.id.layout_city_choose_confirm_btn);
cancelBtn.setOnClickListener(this);
confirmBtn.setOnClickListener(this);
titleView = (TextView) contentView.findViewById(R.id.layout_city_choose_title_tv);
setContentView(contentView);

initDates();
}

public DateOrCityChooseLdy(Context context, int style, boolean isDatechoose, int minYear) {
super(context, style);
this.context = context;
this.isDatechoose = isDatechoose;
this.minYear = minYear;
contentView = (ViewGroup) LayoutInflater.from(context).inflate(R.layout.layout_city_choose_ldy, null);
yearWv = (WheelView) contentView.findViewById(R.id.layout_city_choose_province_wv);
yearWv.addChangingListener(this);
monthWv = (WheelView) contentView.findViewById(R.id.layout_city_choose_city_wv);
monthWv.addChangingListener(this);
dayWv = (WheelView) contentView.findViewById(R.id.layout_city_choose_district_wv);
dayWv.addChangingListener(this);
yearWv.setShadowColor(0xf0f0f0, 0xf0f0f0, 0xf0f0f0);// 设置颜色
monthWv.setShadowColor(0xf0f0f0, 0xf0f0f0, 0xf0f0f0);
dayWv.setShadowColor(0xf0f0f0, 0xf0f0f0, 0xf0f0f0);
setVisibleItems(visibleItems);
cancelBtn = (Button) contentView.findViewById(R.id.layout_city_choose_cancel_btn);
confirmBtn = (TextView) contentView.findViewById(R.id.layout_city_choose_confirm_btn);
cancelBtn.setOnClickListener(this);
confirmBtn.setOnClickListener(this);
titleView = (TextView) contentView.findViewById(R.id.layout_city_choose_title_tv);
setContentView(contentView);
initDates();
}


public DateOrCityChooseLdy(Context context, int style, boolean isDatechoose, int minYear, int maxMonth) {
super(context, style);
this.context = context;
this.isDatechoose = isDatechoose;
this.minYear = minYear;
this.maxMonth = maxMonth;
contentView = (ViewGroup) LayoutInflater.from(context).inflate(R.layout.layout_city_choose_ldy, null);
yearWv = (WheelView) contentView.findViewById(R.id.layout_city_choose_province_wv);
yearWv.addChangingListener(this);
monthWv = (WheelView) contentView.findViewById(R.id.layout_city_choose_city_wv);
monthWv.addChangingListener(this);
dayWv = (WheelView) contentView.findViewById(R.id.layout_city_choose_district_wv);
dayWv.addChangingListener(this);
yearWv.setShadowColor(0xf0f0f0, 0xf0f0f0, 0xf0f0f0);// 设置颜色
monthWv.setShadowColor(0xf0f0f0, 0xf0f0f0, 0xf0f0f0);
dayWv.setShadowColor(0xf0f0f0, 0xf0f0f0, 0xf0f0f0);
setVisibleItems(visibleItems);
cancelBtn = (Button) contentView.findViewById(R.id.layout_city_choose_cancel_btn);
confirmBtn = (TextView) contentView.findViewById(R.id.layout_city_choose_confirm_btn);
cancelBtn.setOnClickListener(this);
confirmBtn.setOnClickListener(this);
titleView = (TextView) contentView.findViewById(R.id.layout_city_choose_title_tv);
setContentView(contentView);
initDates();
}

public DateOrCityChooseLdy(Context context, int style, boolean isDatechoose) {
super(context, style);
this.context = context;
this.isDatechoose = isDatechoose;
contentView = (ViewGroup) LayoutInflater.from(context).inflate(R.layout.layout_city_choose_ldy, null);
yearWv = (WheelView) contentView.findViewById(R.id.layout_city_choose_province_wv);
yearWv.addChangingListener(this);
monthWv = (WheelView) contentView.findViewById(R.id.layout_city_choose_city_wv);
monthWv.addChangingListener(this);
dayWv = (WheelView) contentView.findViewById(R.id.layout_city_choose_district_wv);
dayWv.addChangingListener(this);
yearWv.setShadowColor(0xf0f0f0, 0xf0f0f0, 0xf0f0f0);// 设置颜色
monthWv.setShadowColor(0xf0f0f0, 0xf0f0f0, 0xf0f0f0);
dayWv.setShadowColor(0xf0f0f0, 0xf0f0f0, 0xf0f0f0);
setVisibleItems(visibleItems);
cancelBtn = (Button) contentView.findViewById(R.id.layout_city_choose_cancel_btn);
confirmBtn = (TextView) contentView.findViewById(R.id.layout_city_choose_confirm_btn);
cancelBtn.setOnClickListener(this);
confirmBtn.setOnClickListener(this);
titleView = (TextView) contentView.findViewById(R.id.layout_city_choose_title_tv);
setContentView(contentView);
initDates();
}

public DateOrCityChooseLdy(Context context, int style, boolean isDatechoose, boolean isToToday) {
super(context, style);
this.context = context;
this.isDatechoose = isDatechoose;
this.isToToday = isToToday;
contentView = (ViewGroup) LayoutInflater.from(context).inflate(R.layout.layout_city_choose_ldy, null);
yearWv = (WheelView) contentView.findViewById(R.id.layout_city_choose_province_wv);
yearWv.addChangingListener(this);
monthWv = (WheelView) contentView.findViewById(R.id.layout_city_choose_city_wv);
monthWv.addChangingListener(this);
dayWv = (WheelView) contentView.findViewById(R.id.layout_city_choose_district_wv);
dayWv.addChangingListener(this);
yearWv.setShadowColor(0xf0f0f0, 0xf0f0f0, 0xf0f0f0);// 设置颜色
monthWv.setShadowColor(0xf0f0f0, 0xf0f0f0, 0xf0f0f0);
dayWv.setShadowColor(0xf0f0f0, 0xf0f0f0, 0xf0f0f0);
setVisibleItems(visibleItems);
cancelBtn = (Button) contentView.findViewById(R.id.layout_city_choose_cancel_btn);
confirmBtn = (TextView) contentView.findViewById(R.id.layout_city_choose_confirm_btn);
cancelBtn.setOnClickListener(this);
confirmBtn.setOnClickListener(this);
titleView = (TextView) contentView.findViewById(R.id.layout_city_choose_title_tv);
setContentView(contentView);
initDates();
}

public DateOrCityChooseLdy(Context context) {
this(context, null, true);
this.isDatechoose = true;
}

/**
* 更新显示日
*/
private void updateData() {
if (isDatechoose) {
int currentItem = yearWv.getCurrentItem();
String string = years[currentItem];

Time time = new Time();
time.setToNow();
if (string.equals(time.year + "年")) {
months = new String[maxMonth];
for (int i = 0; i < maxMonth; i++) {
months[i] = (i + 1) + "月";
}
} else {
months = new String[12];
for (int i = 0; i < 12; i++) {
months[i] = (i + 1) + "月";
}

}

monthWv.setViewAdapter(new ArrayWheelAdapter<String>(context, months));

String str1 = string.substring(0, string.length() - 1);

int currentItem2 = monthWv.getCurrentItem();
if (months.length < currentItem2 + 1) {
currentItem2 = months.length - 1;
}
String string2 = months[currentItem2];
monthWv.setCurrentItem(currentItem2, true);

boolean isCurrentYearMonth = false;
if (string2.equals((time.month + 1) + "月") && string.equals(time.year + "年")) {
isCurrentYearMonth = true;//wheelview选中年月为当前年月
}
String str2 = string2.substring(0, string2.length() - 1);

if (Integer.parseInt(str1) % 4 == 0 && Integer.parseInt(str1) % 100 != 0 || Integer.parseInt(str1) % 400 == 0) {
if (str2.equals("1") || str2.equals("3") || str2.equals("5") || str2.equals("7") || str2.equals("8") || str2.equals("10") || str2.equals("12")) {
if (isToToday && isCurrentYearMonth) {
maxDay = DateUtil.getDay();
} else {
maxDay = 31;
}
days = new String[maxDay];
for (int i = 0; i < maxDay; i++) {
days[i] = (i + 1) + "日";
}
} else if (str2.equals("4") || str2.equals("6") || str2.equals("9") || str2.equals("11")) {
if (isToToday && isCurrentYearMonth) {
maxDay = DateUtil.getDay();
} else {
maxDay = 30;
}
days = new String[maxDay];
for (int i = 0; i < maxDay; i++) {
days[i] = (i + 1) + "日";
}
} else {
if (isToToday && isCurrentYearMonth) {
maxDay = DateUtil.getDay();
} else {
maxDay = 29;
}
days = new String[maxDay];
for (int i = 0; i < maxDay; i++) {
days[i] = (i + 1) + "日";
Debug.e(TAG, "year:" + " 2月:" + string + days[i]);
System.out.print("year:" + " 2月:" + string + days[i]);
}
}
} else {
if (str2.equals("1") || str2.equals("3") || str2.equals("5") || str2.equals("7") || str2.equals("8") || str2.equals("10") || str2.equals("12")) {
if (isToToday && isCurrentYearMonth) {
maxDay = DateUtil.getDay();
} else {
maxDay = 31;
}
days = new String[maxDay];
for (int i = 0; i < maxDay; i++) {
days[i] = (i + 1) + "日";
}
} else if (str2.equals("4") || str2.equals("6") || str2.equals("9") || str2.equals("11")) {
if (isToToday && isCurrentYearMonth) {
maxDay = DateUtil.getDay();
} else {
maxDay = 30;
}
days = new String[maxDay];
for (int i = 0; i < maxDay; i++) {
days[i] = (i + 1) + "日";
}
} else {
if (isToToday && isCurrentYearMonth) {
maxDay = DateUtil.getDay();
} else {
maxDay = 28;
}
days = new String[maxDay];
for (int i = 0; i < maxDay; i++) {
days[i] = (i + 1) + "日";
Debug.e(TAG, "year:" + " 2月:" + string + days[i]);

}
}
}
dayWv.setViewAdapter(new ArrayWheelAdapter<String>(context, days));
dayWv.setCurrentItem(0);
} else {
if (yearWv.getViewAdapter() == null) {
yearWv.setViewAdapter(new ArrayWheelAdapter<String>(context, provinceDatas));
}

updateCities();

updateDistrict();

updateZipCode(0);
}
}

/**
* 更新显示的城市数据
*/
private void updateCities() {
int provinceItem = yearWv.getCurrentItem();

currentProvince = provinceDatas[provinceItem];
String[] cities = citiesMap.get(currentProvince);
if (cities == null) {
cities = new String[]{""};
}

monthWv.setViewAdapter(new ArrayWheelAdapter<String>(context, cities));
monthWv.setCurrentItem(0);
}

/**
* 更新显示的区县数据
*/
private void updateDistrict() {
int cityItem = monthWv.getCurrentItem();
String[] cities = citiesMap.get(currentProvince);

if (cities == null) {
return;
}

currentCity = cities[cityItem];

String[] areas = districsMap.get(currentCity);

if (areas == null) {
areas = new String[]{""};
}

dayWv.setViewAdapter(new ArrayWheelAdapter<String>(context, areas));
dayWv.setCurrentItem(0);
// 增加此句,主要修复只选市,没选区时,一直显示昌平区问题
currentDistrict = districsMap.get(currentCity)[0];
}

/**
* 更新显示邮编
*/
private void updateZipCode(int position) {
currentDistrict = districsMap.get(currentCity)[position];
currentZipCode = zipCodesMap.get(currentDistrict);
}

public int getVisibleItems() {
return visibleItems;
}

/**
* 设置可见条目数
*/
public void setVisibleItems(int visibleItems) {
this.visibleItems = visibleItems;
yearWv.setVisibleItems(visibleItems);
monthWv.setVisibleItems(visibleItems);
dayWv.setVisibleItems(visibleItems);
}

public DateOrCityChooseListener getDateChooseListener() {
return dateChooseListener;
}

/**
* 设置选择器回调
*/
public void setDateOrCityChooseListener(DateOrCityChooseListener dateChooseListener) {
this.dateChooseListener = dateChooseListener;
}

public View getContentView() {
return contentView;
}

/**
* 获取当前年份、 获取当前省
*/
public String getCurrentYear() {
if (isDatechoose) {
int currentItem = yearWv.getCurrentItem();
String string = years[currentItem];
String str1 = string.substring(0, string.length() - 1);
return str1;
} else {
return currentProvince;
}
}

/**
* 获取当前月份 、 获取当前城市
*/
public String getCurrentMonth() {
if (isDatechoose) {
int currentItem2 = monthWv.getCurrentItem();
String string2 = months[currentItem2];
String str2 = string2.substring(0, string2.length() - 1);
return str2;
} else {
return currentCity;
}
}

/**
* 获取当前日 、 获取当前区
*/
public String getCurrentDay() {
if (isDatechoose) {
int currentItem3 = dayWv.getCurrentItem();
String string3 = days[currentItem3];
String str3 = string3.substring(0, string3.length() - 1);
return str3;
} else {
return currentDistrict;
}
}

/**
* 初始化数据
*/
public void initDates() {
/**
* 初始化年月
*/
if (isDatechoose) {

Time time = new Time();
time.setToNow();
int lenth = time.year - minYear;
years = new String[lenth + 1];
int j = 0;
for (int i = minYear; i < time.year + 1; i++) {
years[j] = i + "年";
j++;
}
if (isToToday) {
maxMonth = DateUtil.getMonth();
}
months = new String[maxMonth];
for (int i = 0; i < maxMonth; i++) {
months[i] = (i + 1) + "月";
}

if (yearWv.getViewAdapter() == null) {
yearAdapter = new ArrayWheelAdapter<String>(context, years);
yearWv.setViewAdapter(yearAdapter);
}

updateData();
} else {
/**
* 初始化城市选择
*/
List<ProvinceModel> provinceList = null;
AssetManager asset = context.getAssets();
try {
InputStream input = asset.open("province_data.xml");
// 创建一个解析xml的工厂对象
SAXParserFactory spf = SAXParserFactory.newInstance();
// 解析xml
SAXParser parser = spf.newSAXParser();
XmlParserHandler handler = new XmlParserHandler();
parser.parse(input, handler);
input.close();
// 获取解析出来的数据
provinceList = handler.getDataList();
// 初始化默认选中的省、市、区
if (provinceList != null && !provinceList.isEmpty()) {
currentProvince = provinceList.get(0).getName();
List<CityModel> cityList = provinceList.get(0).getCityList();
if (cityList != null && !cityList.isEmpty()) {
currentCity = cityList.get(0).getName();
List<DistrictModel> districtList = cityList.get(0).getDistrictList();
currentDistrict = districtList.get(0).getName();
currentZipCode = districtList.get(0).getZipcode();
}
}
//
provinceDatas = new String[provinceList.size()];
for (int i = 0; i < provinceList.size(); i++) {
// 遍历所有省的数据
provinceDatas[i] = provinceList.get(i).getName();
List<CityModel> cityList = provinceList.get(i).getCityList();
String[] cityNames = new String[cityList.size()];
for (int j = 0; j < cityList.size(); j++) {
// 遍历省下面的所有市的数据
cityNames[j] = cityList.get(j).getName();
List<DistrictModel> districtList = cityList.get(j).getDistrictList();
String[] distrinctNameArray = new String[districtList.size()];
DistrictModel[] distrinctArray = new DistrictModel[districtList.size()];
for (int k = 0; k < districtList.size(); k++) {
// 遍历市下面所有区/县的数据
DistrictModel districtModel = new DistrictModel(districtList.get(k).getName(), districtList.get(k).getZipcode());
// 区/县对于的邮编,保存到zipCodesMap
zipCodesMap.put(districtList.get(k).getName(), districtList.get(k).getZipcode());
distrinctArray[k] = districtModel;
distrinctNameArray[k] = districtModel.getName();
}
// 市-区/县的数据,保存到districsMap
districsMap.put(cityNames[j], distrinctNameArray);
}
// 省-市的数据,保存到citiesMap
citiesMap.put(provinceList.get(i).getName(), cityNames);
}

updateData();
} catch (Throwable e) {
e.printStackTrace();
} finally {

}
}
}

public interface DateOrCityChooseListener {
/**
* 点击取消按钮
*/
public void onCancel(DateOrCityChooseLdy chooseLdy);

/**
* 点击确认按钮
*/
public void onConfirm(String date, DateOrCityChooseLdy dateChooseLdy);
}

@Override
public void onClick(View v) {
if (dateChooseListener == null) {
return;
}

if (v == cancelBtn) {
dateChooseListener.onCancel(DateOrCityChooseLdy.this);
} else if (v == confirmBtn) {
dateChooseListener.onConfirm(getDate(), DateOrCityChooseLdy.this);
}
}

/**
* 滚动条位置变化时的监听
*/
@Override
public void onChanged(WheelView wheel, int oldValue, int newValue) {
if (isDatechoose) {

if (wheel == monthWv) {
updateData();
} else if (wheel == yearWv) {
updateData();
}
} else {
if (wheel == yearWv) {
updateCities();
updateDistrict();
updateZipCode(0);
} else if (wheel == monthWv) {
updateDistrict();
updateZipCode(0);
} else if (wheel == dayWv) {
updateZipCode(newValue);
}
}
}

public WheelView getYearWv() {
return yearWv;
}

public WheelView getMonthWv() {
return monthWv;
}

public WheelView getDayWv() {
return dayWv;
}

/**
* 获取日期
*/
public String getDate() {
if (isDatechoose) {
String str2 = getCurrentMonth();
String str3 = getCurrentDay();
if (str2.length() != 2) {
str2 = "0" + str2;
}
if (str3.length() != 2) {
str3 = "0" + str3;
}
return getCurrentYear() + "-" + str2 + "-" + str3;
} else {
return getCurrentYear() + " " + getCurrentMonth() + " " + getCurrentDay();
}
}

/**
* 设置最后一个是否显示
*/
public void setLastViewVisible(int VISIBLE) {
dayWv.setVisibility(VISIBLE);
}

/**
* 设置标题
*/
public void setTitle(String title) {
titleView.setText(title);
}

/**
* 设置右边确认btn字
*/
public void setRightText(String Text) {
confirmBtn.setText(Text);
}

/**
* 设置右边确认btn颜色
*/
public void setRightColor(int color) {
confirmBtn.setTextColor(color);
}

/**
* 设置日期的最小年
*/
public void setMinYear(int MinYear) {
if (isDatechoose) {
this.minYear = MinYear;
}
}

/**
* 设置到指定的年
*/
public void setYear(int year) {
if (isDatechoose) {
for (int i = 0; i < years.length; i++) {
if (year == Integer.parseInt(years[i].substring(0, 4))) {
yearWv.setCurrentItem(i);
}
}
}
}

/**
* 设置到指定月
*/
public void setMonth(int month) {
if (isDatechoose) {
for (int i = 0; i < months.length; i++) {
String string = months[i];
if (month == Integer.parseInt(string.substring(0, string.length() - 1))) {
monthWv.setCurrentItem(i);
}
}
}
}

/**
* 设置到指定日
*/
public void setDay(int day) {
if (isDatechoose) {
for (int i = 0; i < days.length; i++) {
String string = days[i];
if (day == Integer.parseInt(string.substring(0, string.length() - 1))) {
dayWv.setCurrentItem(i);
}
}
}
}
}

layout_city_choose_ldy.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF">

<RelativeLayout
android:id="@+id/layout_city_choose_button_rl"
android:layout_width="match_parent"
android:layout_height="50dp"
android:paddingLeft="12dp"
android:paddingRight="12dp">

<Button
android:id="@+id/layout_city_choose_cancel_btn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:background="@drawable/bg_my_info_city_cancel"
android:text="取消"
android:visibility="gone"
android:textColor="#FFFFFF"
android:textSize="14sp" />

<TextView
android:id="@+id/layout_city_choose_confirm_btn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:gravity="center"
android:text="确定"
android:textColor="#f25d56"
android:textSize="14sp" />

<TextView
android:id="@+id/layout_city_choose_title_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="#484848"
android:textSize="16sp" />
</RelativeLayout>

<View
android:id="@+id/layout_city_choose_border_view"
style="@style/ViewSoildLine"
android:layout_below="@id/layout_city_choose_button_rl" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/layout_city_choose_border_view"
android:orientation="horizontal">

<com.u1city.androidframe.Component.wheelview.WheelView
android:id="@+id/layout_city_choose_province_wv"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"></com.u1city.androidframe.Component.wheelview.WheelView>

<com.u1city.androidframe.Component.wheelview.WheelView
android:id="@+id/layout_city_choose_city_wv"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"></com.u1city.androidframe.Component.wheelview.WheelView>

<com.u1city.androidframe.Component.wheelview.WheelView
android:id="@+id/layout_city_choose_district_wv"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"></com.u1city.androidframe.Component.wheelview.WheelView>
</LinearLayout>

</RelativeLayout>

Wheel.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
/*
* Android Wheel Control.
* https://code.google.com/p/android-wheel/
*
* Copyright 2011 Yuri Kanivets
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.u1city.androidframe.Component.wheelview;

import android.content.Context;
import android.database.DataSetObserver;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.GradientDrawable.Orientation;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.Interpolator;
import android.widget.LinearLayout;

import com.u1city.androidframe.R;

import java.util.LinkedList;
import java.util.List;


/**
* Numeric wheel view.
*
* @author Yuri Kanivets
*/
public class WheelView extends View {

/** Top and bottom shadows colors */
/*/ Modified by wulianghuan 2014-11-25
private int[] SHADOWS_COLORS = new int[] { 0xFF111111,
0x00AAAAAA, 0x00AAAAAA };
//*/
private int[] SHADOWS_COLORS = new int[] { 0xefE9E9E9,
0xcfE9E9E9, 0x3fE9E9E9 };


/** Top and bottom items offset (to hide that) */
private static final int ITEM_OFFSET_PERCENT = 0;

/** Left and right padding value */
private static final int PADDING = 10;

/** Default count of visible items */
private static final int DEF_VISIBLE_ITEMS = 5;

// Wheel Values
private int currentItem = 0;

// Count of visible items
private int visibleItems = DEF_VISIBLE_ITEMS;

// Item height
private int itemHeight = 0;

// Center Line
private Drawable centerDrawable;

// Wheel drawables
private int wheelBackground = R.drawable.wheel_bg;
private int wheelForeground = R.drawable.wheel_val;

// Shadows drawables
private GradientDrawable topShadow;
private GradientDrawable bottomShadow;

// Draw Shadows
private boolean drawShadows = true;

// Scrolling
private WheelScroller scroller;
private boolean isScrollingPerformed;
private int scrollingOffset;

// Cyclic
boolean isCyclic = false;

// Items layout
private LinearLayout itemsLayout;

// The number of first item in layout
private int firstItem;

// View adapter
private WheelViewAdapter viewAdapter;

// Recycle
private WheelRecycle recycle = new WheelRecycle(this);

// Listeners
private List<OnWheelChangedListener> changingListeners = new LinkedList<OnWheelChangedListener>();
private List<OnWheelScrollListener> scrollingListeners = new LinkedList<OnWheelScrollListener>();
private List<OnWheelClickedListener> clickingListeners = new LinkedList<OnWheelClickedListener>();

/**
* Constructor
*/
public WheelView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initData(context);
}

/**
* Constructor
*/
public WheelView(Context context, AttributeSet attrs) {
super(context, attrs);
initData(context);
}

/**
* Constructor
*/
public WheelView(Context context) {
super(context);
initData(context);
}

/**
* Initializes class data
* @param context the context
*/
private void initData(Context context) {
scroller = new WheelScroller(getContext(), scrollingListener);
}

// Scrolling listener
WheelScroller.ScrollingListener scrollingListener = new WheelScroller.ScrollingListener() {
@Override
public void onStarted() {
isScrollingPerformed = true;
notifyScrollingListenersAboutStart();
}

@Override
public void onScroll(int distance) {
doScroll(distance);

int height = getHeight();
if (scrollingOffset > height) {
scrollingOffset = height;
scroller.stopScrolling();
} else if (scrollingOffset < -height) {
scrollingOffset = -height;
scroller.stopScrolling();
}
}

@Override
public void onFinished() {
if (isScrollingPerformed) {
notifyScrollingListenersAboutEnd();
isScrollingPerformed = false;
}

scrollingOffset = 0;
invalidate();
}

@Override
public void onJustify() {
if (Math.abs(scrollingOffset) > WheelScroller.MIN_DELTA_FOR_SCROLLING) {
scroller.scroll(scrollingOffset, 0);
}
}
};

/**
* Set the the specified scrolling interpolator
* @param interpolator the interpolator
*/
public void setInterpolator(Interpolator interpolator) {
scroller.setInterpolator(interpolator);
}

/**
* Gets count of visible items
*
* @return the count of visible items
*/
public int getVisibleItems() {
return visibleItems;
}

/**
* Sets the desired count of visible items.
* Actual amount of visible items depends on wheel layout parameters.
* To apply changes and rebuild view call measure().
*
* @param count the desired count for visible items
*/
public void setVisibleItems(int count) {
visibleItems = count;
}

/**
* Gets view adapter
* @return the view adapter
*/
public WheelViewAdapter getViewAdapter() {
return viewAdapter;
}

// Adapter listener
private DataSetObserver dataObserver = new DataSetObserver() {
@Override
public void onChanged() {
invalidateWheel(false);
}

@Override
public void onInvalidated() {
invalidateWheel(true);
}
};

/**
* Sets view adapter. Usually new adapters contain different views, so
* it needs to rebuild view by calling measure().
*
* @param viewAdapter the view adapter
*/
public void setViewAdapter(WheelViewAdapter viewAdapter) {
if (this.viewAdapter != null) {
this.viewAdapter.unregisterDataSetObserver(dataObserver);
}
this.viewAdapter = viewAdapter;
if (this.viewAdapter != null) {
this.viewAdapter.registerDataSetObserver(dataObserver);
}

invalidateWheel(false);
}

/**
* Adds wheel changing listener
* @param listener the listener
*/
public void addChangingListener(OnWheelChangedListener listener) {
changingListeners.add(listener);
}

/**
* Removes wheel changing listener
* @param listener the listener
*/
public void removeChangingListener(OnWheelChangedListener listener) {
changingListeners.remove(listener);
}

/**
* Notifies changing listeners
* @param oldValue the old wheel value
* @param newValue the new wheel value
*/
protected void notifyChangingListeners(int oldValue, int newValue) {
for (OnWheelChangedListener listener : changingListeners) {
listener.onChanged(this, oldValue, newValue);
}
}

/**
* Adds wheel scrolling listener
* @param listener the listener
*/
public void addScrollingListener(OnWheelScrollListener listener) {
scrollingListeners.add(listener);
}

/**
* Removes wheel scrolling listener
* @param listener the listener
*/
public void removeScrollingListener(OnWheelScrollListener listener) {
scrollingListeners.remove(listener);
}

/**
* Notifies listeners about starting scrolling
*/
protected void notifyScrollingListenersAboutStart() {
for (OnWheelScrollListener listener : scrollingListeners) {
listener.onScrollingStarted(this);
}
}

/**
* Notifies listeners about ending scrolling
*/
protected void notifyScrollingListenersAboutEnd() {
for (OnWheelScrollListener listener : scrollingListeners) {
listener.onScrollingFinished(this);
}
}

/**
* Adds wheel clicking listener
* @param listener the listener
*/
public void addClickingListener(OnWheelClickedListener listener) {
clickingListeners.add(listener);
}

/**
* Removes wheel clicking listener
* @param listener the listener
*/
public void removeClickingListener(OnWheelClickedListener listener) {
clickingListeners.remove(listener);
}

/**
* Notifies listeners about clicking
*/
protected void notifyClickListenersAboutClick(int item) {
for (OnWheelClickedListener listener : clickingListeners) {
listener.onItemClicked(this, item);
}
}

/**
* Gets current value
*
* @return the current value
*/
public int getCurrentItem() {
return currentItem;
}

/**
* Sets the current item. Does nothing when index is wrong.
*
* @param index the item index
* @param animated the animation flag
*/
public void setCurrentItem(int index, boolean animated) {
if (viewAdapter == null || viewAdapter.getItemsCount() == 0) {
return; // throw?
}

int itemCount = viewAdapter.getItemsCount();
if (index < 0 || index >= itemCount) {
if (isCyclic) {
while (index < 0) {
index += itemCount;
}
index %= itemCount;
} else{
return; // throw?
}
}
if (index != currentItem) {
if (animated) {
int itemsToScroll = index - currentItem;
if (isCyclic) {
int scroll = itemCount + Math.min(index, currentItem) - Math.max(index, currentItem);
if (scroll < Math.abs(itemsToScroll)) {
itemsToScroll = itemsToScroll < 0 ? scroll : -scroll;
}
}
scroll(itemsToScroll, 0);
} else {
scrollingOffset = 0;

int old = currentItem;
currentItem = index;

notifyChangingListeners(old, currentItem);

invalidate();
}
}
}

/**
* Sets the current item w/o animation. Does nothing when index is wrong.
*
* @param index the item index
*/
public void setCurrentItem(int index) {
setCurrentItem(index, false);
}

/**
* Tests if wheel is cyclic. That means before the 1st item there is shown the last one
* @return true if wheel is cyclic
*/
public boolean isCyclic() {
return isCyclic;
}

/**
* Set wheel cyclic flag
* @param isCyclic the flag to set
*/
public void setCyclic(boolean isCyclic) {
this.isCyclic = isCyclic;
invalidateWheel(false);
}

/**
* Determine whether shadows are drawn
* @return true is shadows are drawn
*/
public boolean drawShadows() {
return drawShadows;
}

/**
* Set whether shadows should be drawn
* @param drawShadows flag as true or false
*/
public void setDrawShadows(boolean drawShadows) {
this.drawShadows = drawShadows;
}

/**
* Set the shadow gradient color
* @param start
* @param middle
* @param end
*/
public void setShadowColor(int start, int middle, int end) {
SHADOWS_COLORS = new int[] {start, middle, end};
}

/**
* Sets the drawable for the wheel background
* @param resource
*/
public void setWheelBackground(int resource) {
wheelBackground = resource;
setBackgroundResource(wheelBackground);
}

/**
* Sets the drawable for the wheel foreground
* @param resource
*/
public void setWheelForeground(int resource) {
wheelForeground = resource;
centerDrawable = getContext().getResources().getDrawable(wheelForeground);
}

/**
* Invalidates wheel
* @param clearCaches if true then cached views will be clear
*/
public void invalidateWheel(boolean clearCaches) {
if (clearCaches) {
recycle.clearAll();
if (itemsLayout != null) {
itemsLayout.removeAllViews();
}
scrollingOffset = 0;
} else if (itemsLayout != null) {
// cache all items
recycle.recycleItems(itemsLayout, firstItem, new ItemsRange());
}

invalidate();
}

/**
* Initializes resources
*/
private void initResourcesIfNecessary() {
if (centerDrawable == null) {
centerDrawable = getContext().getResources().getDrawable(wheelForeground);
}

if (topShadow == null) {
topShadow = new GradientDrawable(Orientation.TOP_BOTTOM, SHADOWS_COLORS);
}

if (bottomShadow == null) {
bottomShadow = new GradientDrawable(Orientation.BOTTOM_TOP, SHADOWS_COLORS);
}

setBackgroundResource(wheelBackground);
}

/**
* Calculates desired height for layout
*
* @param layout
* the source layout
* @return the desired layout height
*/
private int getDesiredHeight(LinearLayout layout) {
if (layout != null && layout.getChildAt(0) != null) {
itemHeight = layout.getChildAt(0).getMeasuredHeight();
}

int desired = itemHeight * visibleItems - itemHeight * ITEM_OFFSET_PERCENT / 50;

return Math.max(desired, getSuggestedMinimumHeight());
}

/**
* Returns height of wheel item
* @return the item height
*/
private int getItemHeight() {
if (itemHeight != 0) {
return itemHeight;
}

if (itemsLayout != null && itemsLayout.getChildAt(0) != null) {
itemHeight = itemsLayout.getChildAt(0).getHeight();
return itemHeight;
}

return getHeight() / visibleItems;
}

/**
* Calculates control width and creates text layouts
* @param widthSize the input layout width
* @param mode the layout mode
* @return the calculated control width
*/
private int calculateLayoutWidth(int widthSize, int mode) {
initResourcesIfNecessary();

// TODO: make it static
itemsLayout.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
itemsLayout.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int width = itemsLayout.getMeasuredWidth();

if (mode == MeasureSpec.EXACTLY) {
width = widthSize;
} else {
width += 2 * PADDING;

// Check against our minimum width
width = Math.max(width, getSuggestedMinimumWidth());

if (mode == MeasureSpec.AT_MOST && widthSize < width) {
width = widthSize;
}
}

itemsLayout.measure(MeasureSpec.makeMeasureSpec(width - 2 * PADDING, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));

return width;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);

buildViewForMeasuring();

int width = calculateLayoutWidth(widthSize, widthMode);

int height;
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else {
height = getDesiredHeight(itemsLayout);

if (heightMode == MeasureSpec.AT_MOST) {
height = Math.min(height, heightSize);
}
}

setMeasuredDimension(width, height);
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
layout(r - l, b - t);
}

/**
* Sets layouts width and height
* @param width the layout width
* @param height the layout height
*/
private void layout(int width, int height) {
int itemsWidth = width - 2 * PADDING;

itemsLayout.layout(0, 0, itemsWidth, height);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

if (viewAdapter != null && viewAdapter.getItemsCount() > 0) {
updateView();

drawItems(canvas);
drawCenterRect(canvas);
}

if (drawShadows) drawShadows(canvas);
}

/**
* Draws shadows on top and bottom of control
* @param canvas the canvas for drawing
*/
private void drawShadows(Canvas canvas) {
/*/ Modified by wulianghuan 2014-11-25
int height = (int)(1.5 * getItemHeight());
//*/
int height = (int)(3 * getItemHeight());
//*/
topShadow.setBounds(0, 0, getWidth(), height);
topShadow.draw(canvas);

bottomShadow.setBounds(0, getHeight() - height, getWidth(), getHeight());
bottomShadow.draw(canvas);
}

/**
* Draws items
* @param canvas the canvas for drawing
*/
private void drawItems(Canvas canvas) {
canvas.save();

int top = (currentItem - firstItem) * getItemHeight() + (getItemHeight() - getHeight()) / 2;
canvas.translate(PADDING, - top + scrollingOffset);

itemsLayout.draw(canvas);

canvas.restore();
}

/**
* Draws rect for current value
* @param canvas the canvas for drawing
*/
private void drawCenterRect(Canvas canvas) {
int center = getHeight() / 2;
int offset = (int) (getItemHeight() / 2 * 1.2);
/*/ Remarked by wulianghuan 2014-11-27 使用自己的画线,而不是描边
Rect rect = new Rect(left, top, right, bottom)
centerDrawable.setBounds(bounds)
centerDrawable.setBounds(0, center - offset, getWidth(), center + offset);
centerDrawable.draw(canvas);
//*/
Paint paint = new Paint();
paint.setColor(getResources().getColor(R.color.province_line_border));
// 设置线宽
paint.setStrokeWidth((float) 3);
// 绘制上边直线
canvas.drawLine(0, center - offset, getWidth(), center - offset, paint);
// 绘制下边直线
canvas.drawLine(0, center + offset, getWidth(), center + offset, paint);
//*/
}

@Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled() || getViewAdapter() == null) {
return true;
}

switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
if (getParent() != null) {
getParent().requestDisallowInterceptTouchEvent(true);
}
break;

case MotionEvent.ACTION_UP:
if (!isScrollingPerformed) {
int distance = (int) event.getY() - getHeight() / 2;
if (distance > 0) {
distance += getItemHeight() / 2;
} else {
distance -= getItemHeight() / 2;
}
int items = distance / getItemHeight();
if (items != 0 && isValidItemIndex(currentItem + items)) {
notifyClickListenersAboutClick(currentItem + items);
}
}
break;
}

return scroller.onTouchEvent(event);
}

/**
* Scrolls the wheel
* @param delta the scrolling value
*/
private void doScroll(int delta) {
scrollingOffset += delta;

int itemHeight = getItemHeight();
int count = scrollingOffset / itemHeight;

int pos = currentItem - count;
int itemCount = viewAdapter.getItemsCount();

int fixPos = scrollingOffset % itemHeight;
if (Math.abs(fixPos) <= itemHeight / 2) {
fixPos = 0;
}
if (isCyclic && itemCount > 0) {
if (fixPos > 0) {
pos--;
count++;
} else if (fixPos < 0) {
pos++;
count--;
}
// fix position by rotating
while (pos < 0) {
pos += itemCount;
}
pos %= itemCount;
} else {
//
if (pos < 0) {
count = currentItem;
pos = 0;
} else if (pos >= itemCount) {
count = currentItem - itemCount + 1;
pos = itemCount - 1;
} else if (pos > 0 && fixPos > 0) {
pos--;
count++;
} else if (pos < itemCount - 1 && fixPos < 0) {
pos++;
count--;
}
}

int offset = scrollingOffset;
if (pos != currentItem) {
setCurrentItem(pos, false);
} else {
invalidate();
}

// update offset
scrollingOffset = offset - count * itemHeight;
if (scrollingOffset > getHeight()) {
scrollingOffset = scrollingOffset % getHeight() + getHeight();
}
}

/**
* Scroll the wheel
* @param itemsToSkip items to scroll
* @param time scrolling duration
*/
public void scroll(int itemsToScroll, int time) {
int distance = itemsToScroll * getItemHeight() - scrollingOffset;
scroller.scroll(distance, time);
}

/**
* Calculates range for wheel items
* @return the items range
*/
private ItemsRange getItemsRange() {
if (getItemHeight() == 0) {
return null;
}

int first = currentItem;
int count = 1;

while (count * getItemHeight() < getHeight()) {
first--;
count += 2; // top + bottom items
}

if (scrollingOffset != 0) {
if (scrollingOffset > 0) {
first--;
}
count++;

// process empty items above the first or below the second
int emptyItems = scrollingOffset / getItemHeight();
first -= emptyItems;
count += Math.asin(emptyItems);
}
return new ItemsRange(first, count);
}

/**
* Rebuilds wheel items if necessary. Caches all unused items.
*
* @return true if items are rebuilt
*/
private boolean rebuildItems() {
boolean updated = false;
ItemsRange range = getItemsRange();
if (itemsLayout != null) {
int first = recycle.recycleItems(itemsLayout, firstItem, range);
updated = firstItem != first;
firstItem = first;
} else {
createItemsLayout();
updated = true;
}

if (!updated) {
updated = firstItem != range.getFirst() || itemsLayout.getChildCount() != range.getCount();
}

if (firstItem > range.getFirst() && firstItem <= range.getLast()) {
for (int i = firstItem - 1; i >= range.getFirst(); i--) {
if (!addViewItem(i, true)) {
break;
}
firstItem = i;
}
} else {
firstItem = range.getFirst();
}

int first = firstItem;
for (int i = itemsLayout.getChildCount(); i < range.getCount(); i++) {
if (!addViewItem(firstItem + i, false) && itemsLayout.getChildCount() == 0) {
first++;
}
}
firstItem = first;

return updated;
}

/**
* Updates view. Rebuilds items and label if necessary, recalculate items sizes.
*/
private void updateView() {
if (rebuildItems()) {
calculateLayoutWidth(getWidth(), MeasureSpec.EXACTLY);
layout(getWidth(), getHeight());
}
}

/**
* Creates item layouts if necessary
*/
private void createItemsLayout() {
if (itemsLayout == null) {
itemsLayout = new LinearLayout(getContext());
itemsLayout.setOrientation(LinearLayout.VERTICAL);
}
}

/**
* Builds view for measuring
*/
private void buildViewForMeasuring() {
// clear all items
if (itemsLayout != null) {
recycle.recycleItems(itemsLayout, firstItem, new ItemsRange());
} else {
createItemsLayout();
}

// add views
int addItems = visibleItems / 2;
for (int i = currentItem + addItems; i >= currentItem - addItems; i--) {
if (addViewItem(i, true)) {
firstItem = i;
}
}
}

/**
* Adds view for item to items layout
* @param index the item index
* @param first the flag indicates if view should be first
* @return true if corresponding item exists and is added
*/
private boolean addViewItem(int index, boolean first) {
View view = getItemView(index);
if (view != null) {
if (first) {
itemsLayout.addView(view, 0);
} else {
itemsLayout.addView(view);
}

return true;
}

return false;
}

/**
* Checks whether intem index is valid
* @param index the item index
* @return true if item index is not out of bounds or the wheel is cyclic
*/
private boolean isValidItemIndex(int index) {
return viewAdapter != null && viewAdapter.getItemsCount() > 0 &&
(isCyclic || index >= 0 && index < viewAdapter.getItemsCount());
}

/**
* Returns view for specified item
* @param index the item index
* @return item view or empty view if index is out of bounds
*/
private View getItemView(int index) {
if (viewAdapter == null || viewAdapter.getItemsCount() == 0) {
return null;
}
int count = viewAdapter.getItemsCount();
if (!isValidItemIndex(index)) {
return viewAdapter.getEmptyItem(recycle.getEmptyItem(), itemsLayout);
} else {
while (index < 0) {
index = count + index;
}
}

index %= count;
return viewAdapter.getItem(index, recycle.getItem(), itemsLayout);
}

/**
* Stops scrolling
*/
public void stopScrolling() {
scroller.stopScrolling();
}
}

调用

dialog_choose_date.xml 这是dialog的布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<?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:background="@drawable/radius_style"
android:paddingBottom="25dp"
android:paddingTop="20dp"
android:paddingLeft="@dimen/dp_10"
android:paddingRight="@dimen/dp_10">


<TextView
android:id="@+id/tv_start_date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|center"
android:text="2020-01-01"
android:textColor="#444"
android:padding="@dimen/dp_10"
android:background="@color/default_app_bg"
android:textSize="16sp" />

<TextView
android:id="@+id/tv_to"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_start_date"
android:layout_marginTop="20dp"
android:gravity="center_vertical|center"
android:text="至"
android:textColor="#444"
android:textSize="16sp" />

<TextView
android:id="@+id/tv_end_date"
android:layout_width="match_parent"
android:padding="@dimen/dp_10"
android:background="@color/default_app_bg"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_to"
android:layout_marginTop="20dp"
android:gravity="center_vertical|center"
android:text="2020-02-01"
android:textColor="#444"
android:textSize="16sp" />

<Button
android:id="@+id/btn_ok"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="@+id/tv_end_date"
android:background="@android:color/holo_blue_dark"
android:padding="10dp"
android:layout_marginTop="33dp"
android:text="确定"
android:textColor="#FFFFFF"
android:textSize="16dp" />

</RelativeLayout>

Activity中调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
private AlertDialog alertDialog;
/**
* 弹出日期范围选择弹窗
*/
private void showDateRangeDialog() {
alertDialog = new AlertDialog.Builder(this).create();
final Window window = alertDialog.getWindow();
alertDialog.show();
window.clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);// 显示软键盘
window.setContentView(R.layout.dialog_choose_date);// 加载自定义布局
final TextView startDateTv = (TextView) window.findViewById(R.id.tv_start_date);
final TextView endDateTv = (TextView) window.findViewById(R.id.tv_end_date);
startDateTv.setText("2020-01-01");
endDateTv.setText("2020-02-01");
startDateTv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String dateStr = startDateTv.getText().toString().trim().replace(" ", "");
showDatePickerDialog(startDateTv, dateStr);
}
});
endDateTv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String dateStr = endDateTv.getText().toString().trim().replace(" ", "");
showDatePickerDialog(endDateTv, dateStr);
}
});

// 确定按键监听
window.findViewById(R.id.btn_ok).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String startDateStr = startDateTv.getText().toString().trim().replace(" ", "");
String endDateStr = endDateTv.getText().toString().trim().replace(" ", "");
if (StringUtils.isEmpty(startDateStr) || StringUtils.isEmpty(endDateStr)) {
ToastUtil.showToastLong(MainStoreActivity.this, "请选择日期!");
} else {
//比较开始日期和结束日期,哪个比较大则作为结束日期传入
String temp;
if (startDateStr.compareTo(endDateStr) > 0){
temp = endDateStr;
endDateStr = startDateStr;
startDateStr = temp;
}
//todo:可以使用这两个日期进行其他的操作

}
}
});
}

/**
* 打开日期选择器,选择具体某一天
*/
private void showDatePickerDialog(final TextView dateTv, String dateStr) {
DateOrCityChooseLdy datePickerDialog = new DateOrCityChooseLdy(mContext, R.style.FullScreenDialog, true, true);
//生日参数不为空。设置日期选择框为用户生日信息
String[] dates = dateStr.split("-");
datePickerDialog.setYear(Integer.valueOf(dates[0]));
datePickerDialog.setMonth(Integer.valueOf(dates[1]));
datePickerDialog.setDay(Integer.valueOf(dates[2]));//设置为当前用户的年月日

datePickerDialog.setDateOrCityChooseListener(new DateOrCityChooseLdy.DateOrCityChooseListener() {
@Override
public void onCancel(DateOrCityChooseLdy chooseLdy) {
chooseLdy.dismiss();
}

@Override
public void onConfirm(String date, DateOrCityChooseLdy dateChooseLdy) {
dateTv.setText(date);
dateChooseLdy.dismiss();
}

});
Window window = datePickerDialog.getWindow();
window.setWindowAnimations(R.style.PopupAnimation);
window.setGravity(Gravity.BOTTOM);
window.getDecorView().setPadding(0, 0, 0, 0);
WindowManager.LayoutParams lp = window.getAttributes();
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
window.setAttributes(lp);
datePickerDialog.show();
}

带输入框的弹窗

示例图

带输入框的弹窗.jpg

ChangePriceDialog.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/**
* 用以更改价格or库存的dialog
*
* @author shenbh
* time 2020-02-13 11:55
* email shenbh@qq.com
* 维护者
*/
public class ChangePriceDialog extends BaseDialog {
private View customView;

private TextView titleTv;

private EditText editText;

private Button confirmBtn;
private Button cancelBtn;

public ChangePriceDialog(Activity context) {
super(context);
setCancelable(true);
customView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_change_price, null);
setContentView(customView);

titleTv = (TextView) customView.findViewById(R.id.dialog_change_type);
editText = (EditText) customView.findViewById(R.id.dialog_change_et);
// editText.setKeyListener(new DigitsKeyListener() {
// @Override
// public int getInputType() {
// return InputType.TYPE_TEXT_VARIATION_PASSWORD;
// }
//
// @Override
// protected char[] getAcceptedChars() {
// char[] data = getStringData(R.string.login_only_can_input).toCharArray();
// return data;
// }
// });
confirmBtn = (Button) customView.findViewById(R.id.ok_btn);
cancelBtn = (Button) customView.findViewById(R.id.cancel_btn);

cancelBtn.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
ChangePriceDialog.this.dismiss();
}
});

WindowManager.LayoutParams params = getWindow().getAttributes();
params.width = dpToPixels(context, 288);
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
getWindow().setAttributes(params);
}

/**
* 获取输入框内容
* @return
*/
public String getText() {
return editText.getText().toString();
}

public void setText(String text) {
editText.setText(text);
}

public View getCustomView() {
return customView;
}

/**
* 设置输入的位数
*/
public void setTextLimit(int digit) {
editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(digit)});
}

/**
* 设置小数点后两位数
*/
public void setDecimalLimit(){
editText.addTextChangedListener(new TextWatcher() {
private int selectionStart;
private int selectionEnd;
private CharSequence temp;

@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
temp = s;
}

@Override
public void afterTextChanged(Editable s) {
selectionStart = editText.getSelectionStart();
selectionEnd = editText.getSelectionEnd();

if (!isOnlyPointNumber(editText.getText().toString())){
//删除多余输入的字(不会显示出来)
s.delete(selectionStart - 1, selectionEnd);
editText.setText(s);
}
}
});
}

/**
* 设置保留两位小数
* @param number
* @return
*/
public boolean isOnlyPointNumber(String number) {//保留两位小数正则
Pattern pattern = Pattern.compile("^\\d+\\.?\\d{0,2}$");
Matcher matcher = pattern.matcher(number);
return matcher.matches();
}

/**设置输入框的inputType
* @param inputType
* InputType.TYPE_CLASS_NUMBER 输入类型为数字文本
* InputType.TYPE_NUMBER_FLAG_DECIMAL 输入类型为小数数字,允许十进制小数点提供分数值
*/
public void setEdtInputType(int inputType){
editText.setInputType(inputType);
}

/**
* 设置标题的文案
* @param text
*/
public void setCustomTitle(String text) {
titleTv.setText(text);
}

/**
* 设置确认按钮的文案
* @param text
*/
public void setConfirmText(String text) {
confirmBtn.setText(text);
}

/**
* 设置取消按钮的文案
* @param text
*/
public void setCancelText(String text) {
cancelBtn.setText(text);
}

/**
* 设置"确认"的监听事件
* @param onClickListener
*/
public void setConfirmListener(View.OnClickListener onClickListener) {
confirmBtn.setOnClickListener(onClickListener);
}

/**
* 设置"取消"的监听事件
* @param onClickListener
*/
public void setCancelListener(View.OnClickListener onClickListener) {
cancelBtn.setOnClickListener(onClickListener);
}

@Override
public void onClick(View v) {

}

@Override
public void show() {
super.show();
keyBoradHandler(editText);
}

private void keyBoradHandler(View v) {
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
InputMethodManager imm = (InputMethodManager) getContext().
getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(customView, 0); //显示软键盘
imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS); //显示软键盘
}

//设置光标位置
public void setPosition() {
CharSequence text = editText.getText();
//Debug.asserts(text instanceof Spannable);
if (text instanceof Spannable) {
Spannable spanText = (Spannable) text;
Selection.setSelection(spanText, text.length());
}
}

public static int dpToPixels(Context context, float dp) {
Resources res = context.getResources();
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, res.getDisplayMetrics());
return (int) px;
}

}

dialog_change_price.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="288dp"
android:layout_height="wrap_content"
android:background="@color/white"
android:gravity="center"
android:padding="27dp"
android:orientation="vertical">

<TextView
android:id="@+id/dialog_change_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="售价"
android:paddingBottom="@dimen/dp_10"
android:paddingTop="@dimen/dp_10"
android:gravity="center_vertical"
android:textColor="#444"
android:textSize="16sp" />

<EditText
android:id="@+id/dialog_change_et"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_alignTop="@+id/dialog_change_type"
android:layout_marginLeft="10dp"
android:layout_toRightOf="@+id/dialog_change_type"
android:layout_alignBottom="@+id/dialog_change_type"
android:background="@drawable/bg_about_app_item"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:textColor="#444"
android:textColorHint="#999"
android:textSize="16dp" />


<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/dialog_change_type"
android:orientation="horizontal">

<Button
android:id="@+id/ok_btn"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_marginTop="28dp"
android:layout_weight="1"
android:background="@drawable/bg_solid_23b4f3_corners_3"
android:gravity="center"
android:text="确认"
android:textColor="#ffffff"
android:textSize="15sp" />


<Button
android:id="@+id/cancel_btn"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_marginTop="28dp"
android:layout_weight="1"
android:layout_marginLeft="@dimen/dp_10"
android:background="@drawable/bg_border_dddddd_corners_3"
android:gravity="center"
android:text="取消"
android:textColor="#999999"
android:textSize="15sp" />


</LinearLayout>

</RelativeLayout>

在Activity中调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ChangePriceDialog changePriceDialog = new ChangePriceDialog(this);
changePriceDialog.setCustomTitle(changeType == 0 ? "售价": "库存");
changePriceDialog.setEdtInputType(changeType == 0 ? (InputType.TYPE_CLASS_NUMBER|InputType.TYPE_NUMBER_FLAG_DECIMAL|InputType.TYPE_NUMBER_VARIATION_NORMAL) : InputType.TYPE_CLASS_NUMBER);
if (changeType == 0) {
changePriceDialog.setDecimalLimit();
}
changePriceDialog.setTextLimit(8);
changePriceDialog.setConfirmListener(new OnClickListener() {
@Override
public void onClick(View v) {

}
});
changePriceDialog.show();

带一个/两个按钮的提示dialog

效果图

带一个确认按钮的dialog.png

带两个按钮的dialog.png

带两个按钮的dialog.png

CommentTipDialog.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/**
* 拥有确定和确定与取消2种样式dialog
*/
public class CommentTipDialog implements View.OnClickListener{

public static final int OK = 1;
public static final int OK_AND_CANCEL = 2;

/**
* dialog类型
*/
private int mDialogType;
private Context mContext;

private TextView okBtn;
private TextView cancelBtn;
private TextView dialogTitleTv;
private AlertDialog alertDialog;
/**
* 内容文本
*/
private String dialogTitle;
/**
* 确定文本
*/
private String okStr;
/**
* 取消文本
*/
private String cancelStr;


public CommentTipDialog(Context context, int dialogType) {
this.mContext = context;
this.mDialogType = dialogType;
}

public void show(){
alertDialog = new AlertDialog.Builder(mContext).create();
alertDialog.show();
if(mDialogType == OK){
alertDialog.setContentView(R.layout.dialog_alert);
okBtn = (TextView) alertDialog.findViewById(R.id.ok_btn);
okBtn.setOnClickListener(this);
}else if(mDialogType == OK_AND_CANCEL){
alertDialog.setContentView(R.layout.dialog_confirm);
okBtn = (TextView) alertDialog.findViewById(R.id.ok_btn);
cancelBtn = (TextView) alertDialog.findViewById(R.id.cancel_btn);
okBtn.setOnClickListener(this);
cancelBtn.setOnClickListener(this);
}

dialogTitleTv = (TextView) alertDialog.findViewById(R.id.dialog_title);

if(!StringUtils.isEmpty(dialogTitle)){
dialogTitleTv.setText(dialogTitle);
}
if(!StringUtils.isEmpty(okStr)){
okBtn.setText(okStr);
}
if(!StringUtils.isEmpty(cancelStr)){
cancelBtn.setText(cancelStr);
}

}

public void setCancelStr(String cancelStr) {
this.cancelStr = cancelStr;
}

public void setDialogTitle(String dialogTitle) {
this.dialogTitle = dialogTitle;
}

public void setOkStr(String okStr) {
this.okStr = okStr;
}

@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.ok_btn:
listener.commonDialogClick(view);
break;
case R.id.cancel_btn:
dismiss();
break;
}
}

public interface OnCommonDialogClickListener{
void commonDialogClick(View view);
}

public OnCommonDialogClickListener listener;

public void setOnCommonDialogClickListener(OnCommonDialogClickListener l){
this.listener = l;
}

/**
* dialog消失
*/
public void dismiss(){
if(alertDialog.isShowing()){
alertDialog.dismiss();
}
}

}

dialog_alert.xml 带一个按钮的dialog的布局文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?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="wrap_content"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:paddingTop="28dp"
android:paddingBottom="28dp"

android:background="@drawable/corner_white"
android:orientation="vertical">

<TextView
android:id="@+id/dialog_title"
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="7dp"
android:text=""
android:textColor="#444444"
android:textSize="16sp"/>

<TextView
android:id="@+id/ok_btn"
android:layout_marginTop="28dp"
android:layout_width="match_parent"
android:minWidth="400dp"
android:layout_height="40dp"
android:textColor="#ffffff"
android:textSize="15sp"
android:text="我知道了"
android:gravity="center"
android:background="@drawable/corner_ff5252"/>

</LinearLayout>

drawable/corner_ff5252.xml

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#ff5252" />
<corners android:radius="3dp" />
<padding
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
android:top="5dp" />
</shape>

dialog_confirm.xml 带两个按钮的dialog的布局文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?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="wrap_content"
android:padding="28dp"
android:background="@drawable/corner_white"
android:orientation="vertical">

<TextView
android:id="@+id/dialog_title"
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="7dp"
android:text=""
android:textColor="#444444"
android:textSize="16sp"/>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">


<TextView
android:id="@+id/cancel_btn"
android:layout_marginTop="28dp"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="40dp"
android:textColor="#999999"
android:textSize="15sp"
android:text="取消"
android:gravity="center"
android:background="@drawable/corner_ffffff"/>

<TextView
android:id="@+id/ok_btn"
android:layout_marginTop="28dp"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="40dp"
android:textColor="#ffffff"
android:textSize="15sp"
android:layout_marginLeft="27dp"
android:text="我知道了"
android:gravity="center"
android:background="@drawable/corner_ff5252"/>

</LinearLayout>

</LinearLayout>

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 一个按钮
*/
private void showRuleDialog(String rule) {
final CommentTipDialog dialog = new CommentTipDialog(this, CommentTipDialog.OK);
dialog.setOkStr("我知道了");
dialog.setDialogTitle(rule);
dialog.show();
dialog.setOnCommonDialogClickListener(new CommentTipDialog.OnCommonDialogClickListener() {
@Override
public void commonDialogClick(View view) {
//点击按钮后的一些事件
dialog.dismiss();
}
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 两个按钮
*/
private void showRuleDialog(String rule) {
final CommentTipDialog dialog = new CommentTipDialog(this, CommentTipDialog.OK_AND_CANCEL);
dialog.setOkStr("确定");
dialog.setCancelStr("取消");
dialog.setDialogTitle(rule);
dialog.show();
dialog.setOnCommonDialogClickListener(new CommentTipDialog.OnCommonDialogClickListener() {
@Override
public void commonDialogClick(View view) {
//点确认按钮后的一些事件
}
});
}

Dialog去除边框

先新建一个Style

1
2
3
4
5
6
7
8
9
10
<!--Dialog样式   没有四周边框-->
<style name="ShareDialog" parent="android:Theme.Dialog">
<item name="android:windowFrame">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:background">@color/colorTransparent</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:backgroundDimAmount">0.7</item>
</style>

新建一个类继承Dialog

1
2
3
4
5
public class OBDPopDialog extends Dialog {
public OBDPopDialog(@NonNull Context context) {
super(context, R.style.ShareDialog);
}
}

然后就和一般的Dialog用法一样了(下面代码附带让Dialog出现位置以及展示大小)

1
2
3
4
5
6
final OBDPopDialog dialog = new OBDPopDialog(mContext);
View view_rd = LayoutInflater.from(mContext).inflate(R.layout.dialog_display_remove_display, null);
setPromptWin(dialog);
dialog.setContentView(view_rd);
dialog.setCanceledOnTouchOutside(true);
dialog.show();

里面的那个方法就是控制位置和大小的

1
2
3
4
5
6
7
8
private void setPromptWin(OBDPopDialog dia) {
Window win = dia.getWindow();
WindowManager.LayoutParams lp = win.getAttributes();
win.setGravity(Gravity.LEFT | Gravity.TOP);
lp.x = (int) (ScreenUtils.getScreenWidth(mContext) * 0.141333);
lp.y = (int) (ScreenUtils.getScreenHeight(mContext) * 0.293663);
win.setAttributes(lp);
}

Dialog设置全屏时隐藏状态栏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class OBDDialogP extends Dialog {
public OBDDialogP(@NonNull Context context) {
super(context , R.style.kdialog);
setCancelable(false);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
applyCompat();
}

private void applyCompat() {
if (Build.VERSION.SDK_INT < 19) {
return;
}
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
}

里面的Style 文件:

1
2
3
4
5
6
7
8
9
<!--Dialog 样式  四周没有边框 加 全屏时不会有隐藏标题栏-->
<style name="kdialog" parent="@android:style/Theme.Dialog">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowFrame">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowIsTranslucent">false</item>
<item name="android:backgroundDimEnabled">false</item>
</style>

调用的时候

1
2
3
4
5
6
7
OBDDialogP dialog = new OBDDialogP(this);
View viewDialog = LayoutInflater.from(this).inflate(R.layout.dialog_perfoemance_other, null);

dialog.setContentView(viewDialog);
dialog.setCanceledOnTouchOutside(false);
dialog.show();
setPromptWin(dialog);

自定义方法:

1
2
3
4
5
6
7
8
private void setPromptWin(OBDDialogP dia) {
WindowManager windowManager = getWindowManager();
Display display = windowManager.getDefaultDisplay();
WindowManager.LayoutParams lp = dia.getWindow().getAttributes();
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = WindowManager.LayoutParams.MATCH_PARENT;
dia.getWindow().setAttributes(lp);
}

Dialog全屏(不隐藏状态栏)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import android.app.Activity;
import android.app.Dialog;
import android.graphics.Color;
import android.os.Build;

public class NewSearchMoreDialog extends Dialog {
private Activity mContext;
private FrameLayout toolbar_search_more_fl;

public NewSearchMoreDialog(final Activity context) {
this(context, R.style.MyDialogStyle);
}

public NewSearchMoreDialog(final Activity context, int themeId) {
super(context, themeId);
mContext = context;
getWindow().setGravity(Gravity.CENTER);
setCancelable(true);
setCanceledOnTouchOutside(true);
LayoutInflater from = LayoutInflater.from(context);
View contentView = from.inflate(R.layout.dialog_searchmore, null);
setContentView(contentView);
getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
getWindow().getDecorView().setBackground(null);
//设置状态栏字体颜色是“黑色”
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
getWindow().setStatusBarColor(Color.BLACK);
}
initView(contentView);
//initData();
}

private void initView(View view) {
toolbar_search_more_fl = view.findViewById(R.id.toolbar_search_more_fl);
//...
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">

<!-- 非全屏(不延伸到状态栏下) -->
<style name="MyDialogStyle">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowFrame">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
<item name="android:backgroundDimEnabled">true</item>
</style>

<!-- 全屏(延伸到状态栏底下) -->
<style name="MyDialogStyleFullScreen">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowFrame">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">false</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
<item name="android:backgroundDimEnabled">true</item>
</style>

</resources>

使用

1
2
3
4
5
6
7
8
if (newSearchMoreDialog == null) {
if (Dialog不要全屏的条件) {
newSearchMoreDialog = new NewSearchMoreDialog(getActivity());
} else {
//
newSearchMoreDialog = new NewSearchMoreDialog(getActivity(), R.style.MyDialogStyleFullScreen);
}
}

dialog禁止系统返回键(包含手势)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//dialog禁止系统返回键(包含手势)
DialogInterface.OnKeyListener keyListener = (dialog, keyCode, event) -> {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0){
return true;
} else {
return false;
}
};

//在把这个listener注册到dialog里面去 当初始化dialog的时候
builder.setTitle(getText(R.string.XXXX))
.setMessage(getText(R.XXXXXX))
.setOnKeyListener(key).setCancelable(false)
.setPositiveButton(android.R.string.ok, someOKButtonListener)
.setCanceledOnTouchOutside(false)
.setNegativeButton(android.R.string.cancel, null);

弹软键盘后再弹Dialog,软键盘不要收缩

Dialog中加载了ProgressBar,来当全局的loading

  1. Activity的清单文件中不要设置android:windowSoftInputMode,即用默认的
  2. Dialog的style中添加<item name="android:windowSoftInputMode">stateUnchanged</item>
  3. 在Activity初始化完成的时候,editText获取下焦点,让它弹出软键盘

完整代码:

  1. Dialog的style

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <style name="Loading" parent="@android:style/Theme.Dialog">
    <item name="android:windowFrame">@null</item>
    <item name="android:windowIsFloating">true</item>
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowNoTitle">true</item>
    <!-- 设置背景色 透明-->
    <item name="android:background">@android:color/transparent</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <!-- 设置是否显示背景 -->
    <item name="android:backgroundDimEnabled">true</item>
    <!-- 设置背景透明度 -->
    <item name="android:backgroundDimAmount">0</item>
    <!-- 设置点击空白不消失 -->
    <item name="android:windowCloseOnTouchOutside">false</item>
    <item name="android:windowSoftInputMode">stateUnchanged</item>
    </style>
  2. LoadingDialog.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    public abstract class LoadingDialog extends Dialog {
    private Window window;

    public abstract void cancle();

    public LoadingDialog(@NonNull @NotNull Context context) {
    super(context, R.style.Loading);
    //加载布局
    setContentView(R.layout.view_loading);

    //设置Dialog参数
    if (window == null) {
    window = getWindow();
    }
    WindowManager.LayoutParams params = window.getAttributes();
    params.gravity = Gravity.CENTER;
    window.setAttributes(params);
    }

    @Override
    public void onBackPressed() {
    //回调
    cancle();
    //关闭Loading
    dismiss();
    }
    }

    view_loading.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="@dimen/dp64"
    android:layout_height="@dimen/dp64"
    android:background="@drawable/loading_background_20"
    android:gravity="center"
    android:orientation="vertical">

    <RelativeLayout
    android:id="@+id/loading_rl"
    android:layout_width="@dimen/dp40"
    android:layout_height="@dimen/dp40"
    android:gravity="center">

    <ProgressBar
    android:id="@+id/loading"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_vertical"
    android:indeterminateBehavior="repeat"
    android:indeterminateDrawable="@drawable/anim" />
    </RelativeLayout>
    </LinearLayout>
  3. 调用Dialog的地方

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    private LoadingDialog loadingDialog;

    public void showLoading() {
    showLoading(true);
    }

    public void showLoading(boolean cancelable) {
    try {
    if (loadingDialog == null) {
    loadingDialog = new LoadingDialog(mView.getUIContext()) {
    @Override
    public void cancle() {

    }
    };
    }
    loadingDialog.setCanceledOnTouchOutside(cancelable);
    if (mView != null && !(mView.getUIContext() instanceof ViewPager.DecorView)
    && !loadingDialog.isShowing()) {
    loadingDialog.show();
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

    public void dismissLoading() {
    try {
    if (mView != null && !(mView.getUIContext() instanceof ViewPager.DecorView)
    && loadingDialog != null && loadingDialog.isShowing()) {
    loadingDialog.dismiss();
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

xm597的Dialog

BaseDialog

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import android.app.Activity;
import android.app.Dialog;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import androidx.annotation.NonNull;

public abstract class BaseDialog extends Dialog {
private View view;
public Activity mcontext;

public BaseDialog(final Activity context) {
super(context, R.style.BaseDialogStyle);
if (view == null) {
mcontext = context;
view = LayoutInflater.from(context).inflate(getLayoutId(), null);
getWindow().setGravity(setGravity());
setCanceledOnTouchOutside(true);
setContentView(view);
WindowManager.LayoutParams params = getLayoutParams(context);
getWindow().setAttributes(params);
}
}

/**
* 需要重写高度的话重写这个方法
*/
@NonNull
protected WindowManager.LayoutParams getLayoutParams(Activity context) {
WindowManager.LayoutParams params = getWindow().getAttributes();

params.width = getScreenWidthPixels(context);
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
return params;
}

public abstract int getLayoutId();

public View getview() {
return view;
}

//其他位置的话重写这方法
public int setGravity() {
return Gravity.CENTER;
}

@Override
public void show() {
if (!isShowing()){
super.show();
}
}

/**
* 获取屏幕widthPixels
*
* @param context 上下文
* @return widthPixels 屏幕宽
*/
public int getScreenWidthPixels(Context context) {
return getDeviceMetrics(context).widthPixels;
}

/**
* 获取屏幕相关参数
*
* @param context 上下文
* @return metrics
*/
public DisplayMetrics getDeviceMetrics(Context context) {
DisplayMetrics metrics = new DisplayMetrics();
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
if (wm != null) {
Display display = wm.getDefaultDisplay();
display.getMetrics(metrics);
}
return metrics;
}
}

其中的 R.style.BaseDialogStyle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//styles.xml
<!-- 底部弹出动画 -->
<style name="DialogBottomAnim" parent="android:Animation">
<item name="android:windowEnterAnimation">@anim/anim_bottom_in</item>
<item name="android:windowExitAnimation">@anim/anim_bottom_out</item>
</style>

<style name="MyDialogStyle">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowFrame">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
<item name="android:backgroundDimEnabled">true</item>
</style>

<style name="BaseDialogStyle" parent="MyDialogStyle">
<item name="android:windowAnimationStyle">@style/DialogBottomAnim</item>
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//anim_bottom_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="@android:integer/config_shortAnimTime"
android:fromYDelta="100%p"
android:toYDelta="0"/>
</set>


//anim_bottom_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="@android:integer/config_shortAnimTime"
android:fromYDelta="0"
android:toYDelta="100%p"/>
</set>

使用

  1. 单个Rv内容的底部弹窗 public class BaseOneRvDialog<T extends IPickerViewData> extends BaseDialog {}

  2. 单列或两列滚轮的弹窗 public class MultiSalaryDialog extends BaseDialog {}

另一套Dialog(DataBinding)

基础

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;

import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;

public abstract class KBaseFullScreenDialog<VD extends ViewDataBinding> extends Dialog {

protected VD mBinding;

public KBaseFullScreenDialog(@NonNull Context context) {
super(context);
init();
}

public KBaseFullScreenDialog(@NonNull Context context, int themeResId) {
super(context, themeResId);
init();
}

private void init() {
setCancelable(false);
setCanceledOnTouchOutside(false);
requestWindowFeature(Window.FEATURE_NO_TITLE);
View contentView = getLayoutInflater().inflate(setContentViewRes(), null);
setContentView(contentView);
mBinding = DataBindingUtil.bind(contentView);
Window window = getWindow();
if (window != null) {
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
}
onContentViewCreated();
}

public void dismissDialog(View view) {
dismiss();
}

protected abstract int setContentViewRes();

protected abstract void onContentViewCreated();

}

使用-普通弹窗

继承上面的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import android.content.Context;
import android.text.TextUtils;
import android.view.View;

import androidx.annotation.NonNull;

public abstract class BaseShowTipsDialog
extends KBaseFullScreenDialog<LayoutBaseShowTipsDialogBinding> {

public BaseShowTipsDialog(@NonNull Context context) {
super(context);
initDialog();
}

public BaseShowTipsDialog(@NonNull Context context, int themeResId) {
super(context, themeResId);
initDialog();
}

private void initDialog() {
setCancelable(true);
setCanceledOnTouchOutside(true);
setSubContent("", 0, "");
}

@Override
protected int setContentViewRes() {
return R.layout.layout_base_show_tips_dialog;
}

@Override
protected void onContentViewCreated() {
mBinding.setView(this);
}


public void setTipTitle(String title) {
mBinding.setTipTitle(title);
if (TextUtils.isEmpty(title)) {
mBinding.tvTitleBaseShowTipDialog.setVisibility(View.GONE);
} else {
mBinding.tvTitleBaseShowTipDialog.setVisibility(View.VISIBLE);
}
}

public void setTipContent(String content) {
mBinding.setTipContent(content);
if (TextUtils.isEmpty(content)) {
mBinding.tvContentBaseShowTipDialog.setVisibility(View.GONE);
} else {
mBinding.tvContentBaseShowTipDialog.setVisibility(View.VISIBLE);
}
}

public void setSubContent(String subTipTitle, int subTipIcon, String subTipContent) {
mBinding.setSubTipTitle(subTipTitle);
if (TextUtils.isEmpty(subTipTitle)) {
mBinding.tvSubTipTitleBaseShowTipDialog.setVisibility(View.GONE);
} else {
mBinding.tvSubTipTitleBaseShowTipDialog.setVisibility(View.VISIBLE);
}
mBinding.setSubTipIcon(subTipIcon);

mBinding.setSubTipContent(subTipContent);
if (TextUtils.isEmpty(subTipContent)) {
mBinding.tvSubTipBaseShowTipDialog.setVisibility(View.GONE);
} else {
mBinding.tvSubTipBaseShowTipDialog.setVisibility(View.VISIBLE);
}
int subTitleVisible = mBinding.tvSubTipTitleBaseShowTipDialog.getVisibility();
int subTipIconVisible = mBinding.ivSubTipBaseShowTipDialog.getVisibility();
int subTipVisible = mBinding.tvSubTipBaseShowTipDialog.getVisibility();
if (subTitleVisible != View.VISIBLE && subTipIconVisible != View.VISIBLE && subTipVisible != View.VISIBLE) {
mBinding.llSubContentBaseShowTipDialog.setVisibility(View.GONE);
} else {
mBinding.llSubContentBaseShowTipDialog.setVisibility(View.VISIBLE);
}
}

public void setButtons(String left, String center, String right, String single) {
mBinding.setLeftButton(left);
if (TextUtils.isEmpty(left)) {
mBinding.btnLeftBaseShowTipDialog.setVisibility(View.GONE);
} else {
mBinding.btnLeftBaseShowTipDialog.setVisibility(View.VISIBLE);
}
mBinding.setCenterButton(center);
if (TextUtils.isEmpty(center)) {
mBinding.btnCenterBaseShowTipDialog.setVisibility(View.GONE);
} else {
mBinding.btnCenterBaseShowTipDialog.setVisibility(View.VISIBLE);
}
mBinding.setRightButton(right);
if (TextUtils.isEmpty(right)) {
mBinding.btnRightBaseShowTipDialog.setVisibility(View.GONE);
} else {
mBinding.btnRightBaseShowTipDialog.setVisibility(View.VISIBLE);
}
mBinding.setSingleButton(single);
if (TextUtils.isEmpty(single)) {
mBinding.btnSingleBaseShowTipDialog.setVisibility(View.GONE);
} else {
mBinding.btnSingleBaseShowTipDialog.setVisibility(View.VISIBLE);
}
}

public abstract void onLeftButtonClick(View view);

public abstract void onCenterButtonClick(View view);

public abstract void onRightButtonClick(View view);

public abstract void onSingleButtonClick(View view);
}

其中的布局

layout_base_show_tips_dialog.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<data>

<import type="android.view.View" />

<import type="android.text.TextUtils" />

<variable
name="view"
type="xxx.dialog.base.BaseShowTipsDialog" />

<variable
name="tipTitle"
type="String" />

<variable
name="tipContent"
type="String" />

<variable
name="subTipTitle"
type="String" />

<variable
name="subTipContent"
type="String" />

<variable
name="subTipIcon"
type="Integer" />

<variable
name="leftButton"
type="String" />

<variable
name="centerButton"
type="String" />

<variable
name="rightButton"
type="String" />

<variable
name="singleButton"
type="String" />
</data>

<FrameLayout
android:id="@+id/fl_bg_base_show_tips_dialog"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color00FFFFFF"
android:onClick="@{view::dismissDialog}"
android:padding="@dimen/viewSize48">

<androidx.cardview.widget.CardView
android:id="@+id/root_base_show_tips_dialog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@color/colorWhite"
app:cardCornerRadius="@dimen/viewSize5"
app:cardElevation="0dp">

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="@dimen/viewSize16"
android:paddingTop="@dimen/viewSize12"
android:paddingEnd="@dimen/viewSize16">

<TextView
android:id="@+id/tv_title_base_show_tip_dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/viewSize12"
android:gravity="center"
android:text="@{tipTitle}"
android:textColor="@color/colorAppMainText"
android:textSize="@dimen/textSize16"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@id/tv_content_base_show_tip_dialog"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="标题" />

<TextView
android:id="@+id/tv_content_base_show_tip_dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/viewSize6"
android:lineSpacingExtra="@dimen/viewSize3"
android:text="@{tipContent}"
android:textColor="@color/color333333"
android:textSize="@dimen/textSize14"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title_base_show_tip_dialog"
tools:text="提示内容" />

<LinearLayout
android:id="@+id/ll_sub_content_base_show_tip_dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/viewSize12"
android:gravity="center"
android:orientation="horizontal"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_content_base_show_tip_dialog">

<TextView
android:id="@+id/tv_sub_tip_title_base_show_tip_dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{subTipTitle}"
android:textColor="@color/color333333"
android:textSize="@dimen/textSize13"
tools:text="二级内容标题:" />

<ImageView
android:id="@+id/iv_sub_Tip_base_show_tip_dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/viewSize4"
android:contentDescription="@string/app_name"
android:src="@{subTipIcon}"
tools:src="@drawable/icon_mobile_0" />

<TextView
android:id="@+id/tv_sub_Tip_base_show_tip_dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/viewSize8"
android:text="@{subTipContent}"
android:textColor="@color/colorAppTheme"
tools:text="二级提示内容" />
</LinearLayout>

<View
android:id="@+id/h_line_base_show_tip_dialog"
android:layout_width="match_parent"
android:layout_height="@dimen/viewSize1"
android:layout_marginTop="@dimen/viewSize12"
android:background="@color/colorAppDivider"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/ll_sub_content_base_show_tip_dialog" />

<TextView
android:id="@+id/btn_left_base_show_tip_dialog"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:onClick="@{view::onLeftButtonClick}"
android:paddingTop="@dimen/viewSize12"
android:paddingBottom="@dimen/viewSize12"
android:text="@{leftButton}"
android:textColor="@color/colorAppNormalText"
android:textSize="@dimen/textSize14"
app:layout_constraintEnd_toStartOf="@id/btn_center_base_show_tip_dialog"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/h_line_base_show_tip_dialog"
tools:text="左边按钮" />

<TextView
android:id="@+id/btn_center_base_show_tip_dialog"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:onClick="@{view::onCenterButtonClick}"
android:paddingTop="@dimen/viewSize12"
android:paddingBottom="@dimen/viewSize12"
android:text="@{centerButton}"
android:textColor="@color/colorAppMainText"
android:textSize="@dimen/textSize14"
app:layout_constraintEnd_toStartOf="@id/btn_right_base_show_tip_dialog"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toEndOf="@id/btn_left_base_show_tip_dialog"
app:layout_constraintTop_toBottomOf="@id/h_line_base_show_tip_dialog"
tools:text="中间按钮" />

<TextView
android:id="@+id/btn_right_base_show_tip_dialog"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:onClick="@{view::onRightButtonClick}"
android:paddingTop="@dimen/viewSize12"
android:paddingBottom="@dimen/viewSize12"
android:text="@{rightButton}"
android:textColor="@color/colorAppTheme"
android:textSize="@dimen/textSize14"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toEndOf="@id/btn_center_base_show_tip_dialog"
app:layout_constraintTop_toBottomOf="@id/h_line_base_show_tip_dialog"
tools:text="右边按钮" />

<TextView
android:id="@+id/btn_single_base_show_tip_dialog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/viewSize12"
android:background="@drawable/selector_background_1"
android:gravity="center"
android:onClick="@{view::onSingleButtonClick}"
android:paddingTop="@dimen/viewSize10"
android:paddingBottom="@dimen/viewSize10"
android:text="@{singleButton}"
android:textColor="@color/colorWhite"
android:textSize="@dimen/textSize16"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/h_line_base_show_tip_dialog"
tools:text="单一按钮" />
</androidx.constraintlayout.widget.ConstraintLayout>

</androidx.cardview.widget.CardView>
</FrameLayout>
</layout>

调用

安卓/dialog的效果图

1
2
3
4
5
6
7
8
9
SimpleTipDialog tipDialog = new SimpleTipDialog(getActivity());
tipDialog.setTipTitle("提示");//如果不需要标题,那么这一句删除
tipDialog.setTipContent("确定要退出登录吗?");//如果不需要内容,那么这一句删除
tipDialog.setButtons("点错了", "", "退出", "");//如果不需要对应按钮,那么对应按钮的文案设置为空字符串
tipDialog.setSimpleTipDialogListener(() -> {
MySPUtils.logout(getActivity());
getActivity().finish();
});
tipDialog.show();

如果两个按钮都有点击事件,那么用

1
2
3
4
5
6
7
8
9
10
11
tipDialog.setSimpleTipDialogListener1(new SimpleTipDialog.ISimpleTipDialogListener1() {
@Override
public void onCancelClick() {
//这个是左侧按钮的点击事件
}

@Override
public void onConfirmClick() {
//这个是左侧按钮的点击事件
}
});

使用-图片+一个按钮

安卓/dialog的效果图1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

import android.content.Context;
import android.text.TextUtils;
import android.view.View;

import androidx.annotation.NonNull;

import xxx.project.api.impl.bean.ResumeBean;
import xxx.project.cache.GeRenAppCache;
import xxx.project.manager.WechatSDKUtils;
import xxx.utils.datetime.KDateTimeUtils;
import xxx.widget.kdialog.KBaseFullScreenDialog;

import java.util.Calendar;

public class BindWechatCheckDialog extends KBaseFullScreenDialog<LayoutDialogBindWechatBinding> {

public BindWechatCheckDialog(@NonNull Context context) {
super(context);
}

@Override
protected int setContentViewRes() {
return R.layout.layout_dialog_bind_wechat;
}

@Override
protected void onContentViewCreated() {
mBinding.setView(this);
}

public boolean check() {
ResumeBean resumeBean = GeRenAppCache.getResumeCache();
if (resumeBean != null && resumeBean.getResumeRow() != null) {
String showTime = GeRenAppCache.getWechatCheckTime();
String currentDate = KDateTimeUtils.getCurrentDate();
if (TextUtils.isEmpty(showTime) || showTime.compareTo(currentDate) <= 0) {
Calendar instance = Calendar.getInstance();
instance.add(Calendar.DATE, 7);
int year = instance.get(Calendar.YEAR);
int month = instance.get(Calendar.MONTH) + 1;
int date = instance.get(Calendar.DATE);
String nextShowTime = year + "-" + month + "-" + date;
GeRenAppCache.saveWechatCheckTime(nextShowTime);
show();
return true;
} else {
return false;
}
} else {
return false;
}
}

public void cancelDialog(View view) {
dismiss();
}

public void launchMiniProgramRelease(View view) {
dismiss();
WechatSDKUtils.launchMiniProgramRelease(getContext());
}
}

其中的布局

R.layout.layout_dialog_bind_wechat.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<data>

<variable
name="view"
type="com.xm597.app.project.view.dialog.BindWechatCheckDialog" />
</data>

<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<androidx.cardview.widget.CardView
android:layout_width="320dp"
android:layout_height="380dp"
android:layout_gravity="center"
app:cardBackgroundColor="@android:color/white"
app:cardCornerRadius="10dp"
app:cardElevation="0dp">


<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<TextView
android:id="@+id/btn_close_wechat_bind_tips_dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:gravity="center"
android:onClick="@{view::cancelDialog}"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:text="×"
android:textColor="#6E6E6E"
android:textSize="34sp" />

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="绑定微信提醒"
android:textColor="#1D1D1D"
android:textSize="22sp" />

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:gravity="center"
android:text="聊天沟通回复及时知道,重要信息不再错过"
android:textColor="#A6A6A6"
android:textSize="12sp" />

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="4dp"
android:background="@android:color/white"
android:src="@drawable/icon_bind_wechat" />

<TextView
android:id="@+id/btn_bind_wechat_bind_tips_dialog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="58dp"
android:layout_marginTop="8dp"
android:layout_marginRight="58dp"
android:background="@drawable/selector_background_0"
android:gravity="center"
android:onClick="@{view::launchMiniProgramRelease}"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:text="去开启"
android:textColor="@drawable/selector_txtcolor_0"
android:textSize="16sp" />
</LinearLayout>
</androidx.cardview.widget.CardView>

</FrameLayout>
</layout>

调用

1
2
3
4
5
6
7
8
9
10
private BindWechatCheckDialog mBindWechatCheckDialog;//成员变量

if (mBindWechatCheckDialog == null) {
mBindWechatCheckDialog = new BindWechatCheckDialog(this);
mBindWechatCheckDialog.setOnDismissListener(dialog -> mPresenter.mWxSubscribe.setValue(-1));
}
boolean check = mBindWechatCheckDialog.check();
if (!check) {
mPresenter.mWxSubscribe.setValue(-1);
}

Activity伪装成Dialog

在注册清单文件中把这个Activity的theme改成dialog的样式即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.easymorse.dialog" android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".DialogActivity" android:label="@string/app_name"
android:theme="@android:style/Theme.Dialog">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

</application>
<uses-sdk android:minSdkVersion="8" />

</manifest>

DialogFragment

https://github.com/crazyqiang/AndroidStudy

场景

  1. 不用提供布局,内置项目中常用默认的样式
  2. 支持自定义复杂的布局、动画、对话框大小、背景色等设置
  3. 统一管理多个dialog并顺序弹出

使用

引入lib_dialog这个库

1
2
3
4
5
//settings.gradle
include ':lib_dialog'

//app的build.gradle
implementation project(path: ":lib_dialog")

在代码中使用

一个按钮

1
2
3
4
5
6
7
8
9
10
11
//一个按钮
new SYDialog.Builder(this)
.setTitle("我是标题")
.setContent("您好,我们将在30分钟处理,稍后通知您订单结果!")
.setPositiveButton(new IDialog.OnClickListener() {
@Override
public void onClick(IDialog dialog) {
dialog.dismiss();
}
})
.show();

两个按钮

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//两个按钮
new SYDialog.Builder(this)
.setTitle("我是标题")
.setContent("您好,我们将在30分钟处理,稍后通知您订单结果!")
.setPositiveButton(new IDialog.OnClickListener() {
@Override
public void onClick(IDialog dialog) {
dialog.dismiss();
}
})
.setNegativeButton(new IDialog.OnClickListener() {
@Override
public void onClick(IDialog dialog) {
dialog.dismiss();
}
})
.show();

使用自定义布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//使用自定义布局
new SYDialog.Builder(this)
.setDialogView(R.layout.layout_dialog)//设置dialog布局
.setAnimStyle(R.style.translate_style)//设置动画 默认没有动画
.setScreenWidthP(0.85f) //设置屏幕宽度比例 0.0f-1.0f
.setGravity(Gravity.CENTER)//设置Gravity
.setWindowBackgroundP(0.2f)//设置背景透明度 0.0f-1.0f 1.0f完全不透明
.setCancelable(true)//设置是否屏蔽物理返回键 true不屏蔽 false屏蔽
.setCancelableOutSide(true)//设置dialog外点击是否可以让dialog消失
.setBuildChildListener(new IDialog.OnBuildListener() {
//设置子View
@Override
public void onBuildChildView(final IDialog dialog, View view, int layoutRes) {
//dialog: IDialog
//view: DialogView
//layoutRes :Dialog的资源文件 如果一个Activity里有多个dialog 可以通过layoutRes来区分
final EditText editText = view.findViewById(R.id.et_content);
Button btn_ok = view.findViewById(R.id.btn_ok);
btn_ok.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String editTextStr = null;
if (!TextUtils.isEmpty(editText.getText())) {
editTextStr = editText.getText().toString();
}
dialog.dismiss();
Toast.makeText(MyApplication.getApplication(), editTextStr, Toast.LENGTH_SHORT).show();
}
});
}
}).show();

统一管理多个Dialog依次弹出

1
2
3
4
5
6
SYDialog.Builder builder1 = new SYDialog.Builder(this);
SYDialog.Builder builder2 = new SYDialog.Builder(this);
//添加第一个Dialog
SYDialogsManager.getInstance().requestShow(new DialogWrapper(builder1));
//添加第二个Dialog
SYDialogsManager.getInstance().requestShow(new DialogWrapper(builder2));

Dialog引发的内存泄露

就是在activity关闭的时候dialog还在show状态

解决 :(添加lifecycleObserver进行生命周期监听)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import androidx.activity.ComponentActivity;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;

class TipDialog(context: Context) : Dialog(context), LifecycleObserver{
init{
if(context is ComponentActivity){
(context as ComponentActivity).lifecycle.addObserver(this)
}
}
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.item_tip_dialog)
}
@OnLifecycleEvent(Lifecycle.Event.ON_DEESTROY)
private fun onDestroy(){
if(isShowing){
dismiss()
}
}
}

Dialog相关问题

Dialog上使用加载框progressdialog不显示

Dialog改变message无效的问题

1
2
3
4
5
6
7
8
9
10
//关于加载框或者是dialogfragment,中途改变message消息无效的问题:
//参考如下写法,验证有效:
mConnectResultTv.setText(mess);
mConnectResultTv.invalidate();
mConnectResultTv.postDelayed(new Runnable() {
@Override
public void run() {
dismiss();
}
},1000);

dialog不居中的问题

1
2
3
Window dialogWindow = mProgressDlg.getWindow();
WindowManager.LayoutParams lp = dialogWindow.getAttributes();
dialogWindow.setGravity(Gravity.CENTER);
1
2
//去除tile布局     mProgressDlg.requestWindowFeature(Window.FEATURE_NO_TITLE);
mProgressDlg.setContentView(R.layout.dialog_progress);

Unable to add window – token null is not valid

问题详情:android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?

排查:dialog和progressbar等不能在ApplicationContext中创建,需要依托于Activity

解决:

添加了windowSoftInputMode=adjustPan|adjustResize还是会被软键盘盖住

Activity的清单文件中加了 android:windowSoftInputMode="adjustResize|adjustPan",但dialog带edittext还是会被软键盘盖住(不会顶起来)

解决:原来是Activity在清单文件中的主题带有 <item name="android:windowTranslucentStatus" tools:targetApi="19">true</item> 属性,导致这个顶起效果失效,改activity的主题为android:theme="@style/Theme.AppCompat.Light.NoActionBar"

5种方法完美解决android软键盘挡住输入框方法详解-腾讯云开发者社区-腾讯云