77import android .graphics .Typeface ;
88import android .graphics .drawable .ColorDrawable ;
99import android .util .DisplayMetrics ;
10+ import android .util .Log ;
1011import android .util .TypedValue ;
1112import android .view .Gravity ;
1213import android .view .View ;
3233import java .util .List ;
3334
3435public class FileDialogSelectUtils {
36+ private static final String TAG = FileDialogSelectUtils .class .getSimpleName ();
37+ private static final String EMPTY_PLACEHOLDER = "__EMPTY_PLACEHOLDER__" ;
38+
3539 public interface FileSelectCallback {
3640 void onFileSelected (List <File > selectedFiles );
3741 }
@@ -43,10 +47,11 @@ public interface FileSelectCallback {
4347 private final List <File > selectedFiles = new ArrayList <>();
4448 private AlertDialog dialog ;
4549 private FileListAdapter adapter ;
46- private int itemTvSize = 20 ;
50+ private int itemTvSize = 20 ;
4751 private boolean singleSelect = false ;
4852 private ListView listView ;
4953 private TextView titleView ;
54+ private LinearLayout buttonLayout ;
5055 private LinearLayout rootLayout ;
5156
5257 private float widthRatio = 1f ;
@@ -58,7 +63,7 @@ public FileDialogSelectUtils(Context context, File startDir, FileSelectCallback
5863 this .callback = callback ;
5964 }
6065
61- public FileDialogSelectUtils setSizeRatio (float widthRatio , float heightRatio ,int itemTvSize ) {
66+ public FileDialogSelectUtils setSizeRatio (float widthRatio , float heightRatio , int itemTvSize ) {
6267 this .widthRatio = widthRatio ;
6368 this .heightRatio = heightRatio ;
6469 this .itemTvSize = itemTvSize ;
@@ -77,12 +82,10 @@ public FileDialogSelectUtils setSizeRatio(float widthRatio, float heightRatio) {
7782 }
7883
7984 public void show () {
80- // 创建根布局
8185 rootLayout = new LinearLayout (context );
8286 rootLayout .setOrientation (LinearLayout .VERTICAL );
8387 rootLayout .setPadding (30 , 20 , 30 , 20 );
8488
85- // 创建标题
8689 titleView = new TextView (context );
8790 titleView .setTextSize (TypedValue .COMPLEX_UNIT_SP , itemTvSize );
8891 titleView .setGravity (Gravity .LEFT );
@@ -91,37 +94,29 @@ public void show() {
9194 titleView .setTypeface (null , Typeface .BOLD );
9295 rootLayout .addView (titleView );
9396
94- // 创建ListView
9597 listView = new ListView (context );
9698 adapter = new FileListAdapter ();
9799 listView .setAdapter (adapter );
98-
99- // 设置ListView的权重为1,占据剩余空间
100- LinearLayout .LayoutParams listParams = new LinearLayout .LayoutParams (
101- LinearLayout .LayoutParams .MATCH_PARENT ,
102- 0 ,
103- 1.0f
104- );
105- listView .setLayoutParams (listParams );
100+ listView .setLayoutParams (new LinearLayout .LayoutParams (
101+ LinearLayout .LayoutParams .MATCH_PARENT , 0 , 1.0f ));
106102 rootLayout .addView (listView );
107103
108- // 创建按钮布局
109- LinearLayout buttonLayout = new LinearLayout (context );
104+ buttonLayout = new LinearLayout (context );
110105 buttonLayout .setOrientation (LinearLayout .HORIZONTAL );
111106 buttonLayout .setGravity (Gravity .RIGHT );
112107 buttonLayout .setPadding (0 , 20 , 0 , 0 );
113108
114- // 创建取消按钮
115109 Button cancelButton = new Button (context );
116110 cancelButton .setText (context .getString (R .string .iot_cancel ));
117111 cancelButton .setTextSize (TypedValue .COMPLEX_UNIT_SP , itemTvSize );
118- cancelButton .setPadding (20 , 15 , 20 , 15 );
112+ cancelButton .setPadding (20 , 10 , 20 , 10 );
119113 LinearLayout .LayoutParams cancelParams = new LinearLayout .LayoutParams (
120114 LinearLayout .LayoutParams .WRAP_CONTENT ,
121- LinearLayout .LayoutParams .WRAP_CONTENT
122- );
115+ LinearLayout .LayoutParams .WRAP_CONTENT );
123116 cancelParams .setMargins (0 , 0 , 12 , 0 );
117+ cancelButton .setTextColor (Color .BLACK ); // 可根据你设计风格设置
124118 cancelButton .setLayoutParams (cancelParams );
119+ cancelButton .setBackground (ContextCompat .getDrawable (context ,R .drawable .custom_button_background ));
125120 cancelButton .setOnClickListener (new View .OnClickListener () {
126121 @ Override
127122 public void onClick (View v ) {
@@ -130,15 +125,15 @@ public void onClick(View v) {
130125 });
131126 buttonLayout .addView (cancelButton );
132127
133- // 创建确定按钮
134128 Button okButton = new Button (context );
135129 okButton .setText (context .getString (R .string .iot_ok ));
136130 okButton .setTextSize (TypedValue .COMPLEX_UNIT_SP , itemTvSize );
137- okButton .setPadding (20 , 15 , 20 , 15 );
131+ okButton .setPadding (20 , 10 , 20 , 10 );
132+ okButton .setTextColor (Color .BLACK ); // 可根据你设计风格设置
138133 okButton .setLayoutParams (new LinearLayout .LayoutParams (
139134 LinearLayout .LayoutParams .WRAP_CONTENT ,
140- LinearLayout .LayoutParams .WRAP_CONTENT
141- ));
135+ LinearLayout .LayoutParams .WRAP_CONTENT ));
136+ okButton . setBackground ( ContextCompat . getDrawable ( context , R . drawable . custom_button_background ));
142137 okButton .setOnClickListener (new View .OnClickListener () {
143138 @ Override
144139 public void onClick (View v ) {
@@ -154,14 +149,15 @@ public void onClick(View v) {
154149 @ Override
155150 public void onItemClick (AdapterView <?> parent , View view , int position , long id ) {
156151 File item = fileList .get (position );
157- if (item .getName ().equals (".." )) {
152+ if (EMPTY_PLACEHOLDER .equals (item .getName ())) return ;
153+
154+ if (".." .equals (item .getName ())) {
158155 currentDir = currentDir .getParentFile ();
159- refreshFileList ();
156+ FileDialogSelectUtils . this . refreshFileList ();
160157 } else if (item .isDirectory ()) {
161158 currentDir = item ;
162- refreshFileList ();
159+ FileDialogSelectUtils . this . refreshFileList ();
163160 } else {
164- // 文件:选中/取消
165161 if (singleSelect ) {
166162 selectedFiles .clear ();
167163 selectedFiles .add (item );
@@ -193,7 +189,7 @@ private void refreshFileList() {
193189 }
194190
195191 File [] files = currentDir .listFiles ();
196- if (files != null ) {
192+ if (files != null && files . length > 0 ) {
197193 List <File > fileSorted = Arrays .asList (files );
198194 Collections .sort (fileSorted , new Comparator <File >() {
199195 @ Override
@@ -204,72 +200,53 @@ public int compare(File f1, File f2) {
204200 }
205201 });
206202 fileList .addAll (fileSorted );
203+ } else {
204+ fileList .add (new File (EMPTY_PLACEHOLDER ));
207205 }
208206
209- if (adapter != null ) {
210- adapter .notifyDataSetChanged ();
211- }
212-
213- if (titleView != null ) {
214- titleView .setText (context .getString (R .string .iot_directory_title , currentDir .getAbsolutePath ()));
215-
216- // 动态调整Dialog高度
217- adjustDialogHeight ();
218- }
207+ adapter .notifyDataSetChanged ();
208+ titleView .setText (context .getString (R .string .iot_directory_title , currentDir .getAbsolutePath ()));
209+ listView .post (new Runnable () {
210+ @ Override
211+ public void run () {
212+ FileDialogSelectUtils .this .adjustDialogHeight ();
213+ }
214+ });
219215 }
220216
221217 private void adjustDialogHeight () {
222218 if (dialog == null || rootLayout == null ) return ;
223219
224- // 使用post确保布局已经完成
225- rootLayout .post (new Runnable () {
226- @ Override
227- public void run () {
228- Window window = dialog .getWindow ();
229- if (window != null ) {
230- window .clearFlags (WindowManager .LayoutParams .FLAG_DIM_BEHIND );
231-
232- DisplayMetrics metrics = context .getResources ().getDisplayMetrics ();
233- WindowManager .LayoutParams lp = window .getAttributes ();
234- lp .width = (int ) (metrics .widthPixels * widthRatio );
220+ Window window = dialog .getWindow ();
221+ if (window != null ) {
222+ window .clearFlags (WindowManager .LayoutParams .FLAG_DIM_BEHIND );
235223
236- // 计算ListView的实际内容高度
237- int listViewHeight = calculateListViewHeight ();
224+ DisplayMetrics metrics = context .getResources ().getDisplayMetrics ();
225+ WindowManager .LayoutParams lp = window .getAttributes ();
226+ lp .width = (int ) (metrics .widthPixels * widthRatio );
238227
239- // 计算Dialog的其他组件高度(标题、按钮等)
240- int dialogExtraHeight = calculateDialogExtraHeight ();
228+ int listViewHeight = calculateListViewHeight ();
229+ int dialogExtraHeight = calculateDialogExtraHeight ();
230+ int actualContentHeight = listViewHeight + dialogExtraHeight ;
231+ int maxHeight = (int ) (metrics .heightPixels * heightRatio );
241232
242- // 实际内容总高度
243- int actualContentHeight = listViewHeight + dialogExtraHeight ;
244-
245- // 设置的最大高度
246- int maxHeight = (int ) (metrics .heightPixels * heightRatio );
247-
248- // 选择较小的高度
249- lp .height = Math .min (actualContentHeight , maxHeight );
250-
251- window .setAttributes (lp );
252- }
253- }
254- });
233+ lp .height = Math .min (actualContentHeight , maxHeight );
234+ window .setAttributes (lp );
235+ }
255236 }
256237
257238 private int calculateListViewHeight () {
258- if (adapter == null || adapter .getCount () == 0 ) {
259- return 0 ;
260- }
239+ if (adapter == null || adapter .getCount () == 0 ) return 0 ;
261240
262241 int totalHeight = 0 ;
263242 for (int i = 0 ; i < adapter .getCount (); i ++) {
264243 View item = adapter .getView (i , null , listView );
265244 item .measure (
266245 View .MeasureSpec .makeMeasureSpec (0 , View .MeasureSpec .UNSPECIFIED ),
267- View .MeasureSpec .makeMeasureSpec (0 , View .MeasureSpec .UNSPECIFIED )
268- );
246+ View .MeasureSpec .makeMeasureSpec (0 , View .MeasureSpec .UNSPECIFIED ));
269247 totalHeight += item .getMeasuredHeight ();
270248 }
271249
272- // 加上ListView的分隔线高度
273250 if (adapter .getCount () > 1 ) {
274251 totalHeight += (adapter .getCount () - 1 ) * listView .getDividerHeight ();
275252 }
@@ -278,24 +255,28 @@ private int calculateListViewHeight() {
278255 }
279256
280257 private int calculateDialogExtraHeight () {
281- // 估算Dialog其他组件的高度
282- // 包括:标题高度、按钮高度、内边距等
283-
284- DisplayMetrics metrics = context .getResources ().getDisplayMetrics ();
258+ int total = 0 ;
285259
286- // 标题高度(根据itemTvSize估算)
287- int titleHeight = (int ) TypedValue .applyDimension (
288- TypedValue .COMPLEX_UNIT_SP , itemTvSize + 10 , metrics );
260+ if (titleView != null ) {
261+ titleView .measure (
262+ View .MeasureSpec .makeMeasureSpec (rootLayout .getWidth (), View .MeasureSpec .AT_MOST ),
263+ View .MeasureSpec .makeMeasureSpec (0 , View .MeasureSpec .UNSPECIFIED )
264+ );
265+ total += titleView .getMeasuredHeight ();
266+ }
289267
290- // 按钮高度(根据itemTvSize估算)
291- int buttonHeight = (int ) TypedValue .applyDimension (
292- TypedValue .COMPLEX_UNIT_SP , itemTvSize + 20 , metrics );
268+ if (buttonLayout != null ) {
269+ buttonLayout .measure (
270+ View .MeasureSpec .makeMeasureSpec (rootLayout .getWidth (), View .MeasureSpec .AT_MOST ),
271+ View .MeasureSpec .makeMeasureSpec (0 , View .MeasureSpec .UNSPECIFIED )
272+ );
273+ total += buttonLayout .getMeasuredHeight ();
274+ }
293275
294- // 内边距
295- int padding = (int ) TypedValue .applyDimension (
296- TypedValue .COMPLEX_UNIT_DIP , 80 , metrics );
276+ // 加上内边距(上下的 padding)
277+ total += rootLayout .getPaddingTop () + rootLayout .getPaddingBottom ();
297278
298- return titleHeight + buttonHeight + padding ;
279+ return total ;
299280 }
300281
301282 private class FileListAdapter extends BaseAdapter {
@@ -317,27 +298,47 @@ public long getItemId(int position) {
317298 @ Override
318299 public View getView (int position , View convertView , ViewGroup parent ) {
319300 File file = fileList .get (position );
320-
321301 LinearLayout layout = new LinearLayout (context );
322302 layout .setOrientation (LinearLayout .HORIZONTAL );
323- layout .setPadding (24 , 15 , 24 , 15 );
303+ layout .setPadding (22 , 12 , 22 , 12 );
324304 layout .setGravity (Gravity .CENTER_VERTICAL );
325305
326306 TextView nameView = new TextView (context );
327307 nameView .setTextSize (TypedValue .COMPLEX_UNIT_SP , itemTvSize );
328- nameView .setText (file .getName ().equals (".." ) ? context .getString (R .string .iot_back_directory ) : file .getName ());
329- nameView .setLayoutParams (new LinearLayout .LayoutParams (0 , ViewGroup .LayoutParams .WRAP_CONTENT , 1 ));
330- layout .addView (nameView );
331-
332- if (!file .isDirectory () && !file .getName ().equals (".." )) {
333- CheckBox checkBox = new CheckBox (context );
334- checkBox .setChecked (selectedFiles .contains (file ));
335- checkBox .setEnabled (false ); // 控制点击整行而不是 checkbox
336- checkBox .setButtonDrawable (R .drawable .custom_checkbox );
337- layout .addView (checkBox );
308+ nameView .setLayoutParams (new LinearLayout .LayoutParams (
309+ 0 , ViewGroup .LayoutParams .WRAP_CONTENT , 1 ));
310+
311+ if (EMPTY_PLACEHOLDER .equals (file .getName ())) {
312+ nameView .setText (R .string .not_found_file_child_content );
313+ nameView .setTextColor (Color .GRAY );
314+ nameView .setGravity (Gravity .CENTER );
315+ layout .setGravity (Gravity .CENTER );
316+ } else {
317+ nameView .setText (file .getName ().equals (".." ) ?
318+ context .getString (R .string .iot_back_directory ) : file .getName ());
319+
320+ if (!file .isDirectory () && !file .getName ().equals (".." )) {
321+ CheckBox checkBox = new CheckBox (context );
322+ checkBox .setChecked (selectedFiles .contains (file ));
323+ checkBox .setEnabled (false );
324+ checkBox .setButtonDrawable (R .drawable .custom_checkbox );
325+
326+ // 设置右边距(比如 20dp)
327+ LinearLayout .LayoutParams checkBoxParams = new LinearLayout .LayoutParams (
328+ ViewGroup .LayoutParams .WRAP_CONTENT ,
329+ ViewGroup .LayoutParams .WRAP_CONTENT
330+ );
331+ int marginRightPx = (int ) TypedValue .applyDimension (
332+ TypedValue .COMPLEX_UNIT_DIP , 20 , context .getResources ().getDisplayMetrics ());
333+ checkBoxParams .setMargins (0 , 0 , marginRightPx , 0 );
334+ checkBox .setLayoutParams (checkBoxParams );
335+
336+ layout .addView (checkBox );
337+ }
338338 }
339339
340+ layout .addView (nameView );
340341 return layout ;
341342 }
342343 }
343- }
344+ }
0 commit comments