是否有一个简单的示例或教程,如何在Android的ListView
中放置BaseAdapter
(通过XML解析器从PopupWindow
获取值)?
最佳答案
您可能要检查ListPopupWindow
这是我的方法:PopupWrapper
类只是将PopupWindow
包装在一个更友好的类中:
package com.blablabla.android.helpers.gui.dialog;
import com.blablabla.android.helpers.R;
import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.widget.PopupWindow;
/**
* This class does most of the work of wrapping the {@link PopupWindow} so it's
* simpler to use.
*/
public class PopupWrapper implements OnTouchListener {
/** Context where to show the popup */
protected Context context = null;
/** The popup to show */
protected PopupWindow window = null;
/** What to show in the popup */
protected View root = null;
/** Parent/anchor View */
protected View anchor = null;
/** Optional background */
protected Drawable background = null;
/** Window manager */
private WindowManager windowManager;
public PopupWrapper(Activity activity) {
anchor = null;
context = activity;
init();
}
public PopupWrapper(View anchor) {
this.anchor = anchor;
context = anchor.getContext();
init();
}
private void init() {
window = new PopupWindow(context);
window.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
window.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
window.setTouchable(true);
//window.setFocusable(true);
window.setOutsideTouchable(true);
// when a touch even happens outside of the window
// make the window go away
window.setTouchInterceptor(this);
windowManager = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
onCreate();
}
/**
* Anything you want to have happen when created. Probably should create a
* view and setup the event listeners on child views.
*/
protected void onCreate() {
}
/**
* In case there is stuff to do right before displaying.
*/
protected void onShow() {
}
private void preShow() {
if (root == null) {
throw new IllegalStateException(
"setContentView was not called with a view to display.");
}
onShow();
if (background == null) {
window.setBackgroundDrawable(new BitmapDrawable());
} else {
window.setBackgroundDrawable(background);
}
// if using PopupWindow#setBackgroundDrawable this is the only values of
// the width and hight that make it work
// otherwise you need to set the background of the root viewgroup
// and set the popupwindow background to an empty BitmapDrawable
window.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
window.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
window.setTouchable(true);
window.setFocusable(true);
window.setOutsideTouchable(true);
window.setContentView(root);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
window.dismiss();
return true;
}
return false;
}
public void setBackgroundDrawable(Drawable background) {
this.background = background;
}
/**
* Sets the content view. Probably should be called from {@link onCreate}
*
* @param root
* the view the popup will display
*/
public void setContentView(View root) {
this.root = root;
window.setContentView(root);
}
/**
* Will inflate and set the view from a resource id
*
* @param layoutResID
*/
public void setContentView(int layoutResID) {
LayoutInflater inflator = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
setContentView(inflator.inflate(layoutResID, null));
}
/**
* If you want to do anything when {@link dismiss} is called
*
* @param listener
*/
public void setOnDismissListener(PopupWindow.OnDismissListener listener) {
window.setOnDismissListener(listener);
}
/**
* Displays like a popdown menu from the anchor view
*/
public void showLikePopDownMenu() {
showLikePopDownMenu(0, 0);
}
/**
* Displays like a popdown menu from the anchor view.
*
* @param xOffset
* offset in X direction
* @param yOffset
* offset in Y direction
*/
public void showLikePopDownMenu(int xOffset, int yOffset) {
preShow();
window.setAnimationStyle(R.style.Animations_PopDownMenu);
window.showAsDropDown(anchor, xOffset, yOffset);
}
/**
* Displays like a QuickAction from the anchor view.
*/
public void showLikeQuickAction() {
showLikeQuickAction(0, 0);
}
/**
* Displays like a QuickAction from the anchor view.
*
* @param xOffset
* offset in the X direction
* @param yOffset
* offset in the Y direction
*/
public void showLikeQuickAction(int xOffset, int yOffset) {
preShow();
window.setAnimationStyle(R.style.Animations_GrowFromBottom);
int[] location = new int[2];
anchor.getLocationOnScreen(location);
Rect anchorRect = new Rect(location[0], location[1], location[0]
+ anchor.getWidth(), location[1] + anchor.getHeight());
root.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
int rootWidth = root.getMeasuredWidth();
int rootHeight = root.getMeasuredHeight();
int screenWidth = windowManager.getDefaultDisplay().getWidth();
//int screenHeight = windowManager.getDefaultDisplay().getHeight();
int xPos = ((screenWidth - rootWidth) / 2) + xOffset;
int yPos = anchorRect.top - rootHeight + yOffset;
// display on bottom
if (rootHeight > anchorRect.top) {
yPos = anchorRect.bottom + yOffset;
window.setAnimationStyle(R.style.Animations_GrowFromTop);
}
window.showAtLocation(anchor, Gravity.NO_GRAVITY, xPos, yPos);
}
public void dismiss() {
window.dismiss();
}
public void showAtLocation(int gravity, int x, int y) {
window.showAtLocation(anchor, gravity, x, y);
}
}
FileExplorer
类是使用PopupWrapper
的示例:package com.blablabla.android.helpers.gui.dialog.fexplorer;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.blablabla.android.helpers.R;
import com.blablabla.android.helpers.gui.ViewHelper;
import com.blablabla.android.helpers.gui.dialog.PopupWrapper;
import com.blablabla.android.helpers.util.FileHelper;
import com.blablabla.android.helpers.util.Log;
import android.app.Activity;
import android.os.Environment;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ListView;
/**
* Simple file explorer popup window. Only allows selecting one normal file (no
* directory).
*
* @author [email protected]
*
*/
public class FileExplorer extends PopupWrapper implements Runnable,
OnClickListener, OnItemClickListener {
private static final String TAG = FileExplorer.class.getName();
/** ListView for the file listing */
private ListView fileList = null;
/** Top path (cannot go backward than this) */
private File rootPath = new File(Environment.getExternalStorageDirectory()
.getPath());
/** Current path */
private File path = new File(Environment.getExternalStorageDirectory()
.getPath());
/** Selected item */
private File selected = null;
/** Who to notify when file selecting finished */
private OnFileSelectedListener listener = null;
/** Show hidden files or not */
private boolean showHidden = false;
public FileExplorer(Activity activity, boolean showHidden) {
this(activity);
this.showHidden = showHidden;
}
public FileExplorer(Activity activity) {
super(activity);
// View to show on the popup
root = ViewHelper.inflateViewById(activity, R.layout.explorer);
// Parent view
anchor = ViewHelper.getRootView(activity);
// Listeners
initializeViews();
}
/** Initializes View listeners */
private void initializeViews() {
// Set up the popup window
window.setFocusable(true);
window.setContentView(root);
window.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
window.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
window.setClippingEnabled(true);
// Set up ListView
fileList = (ListView) root.findViewById(R.id.explorer_list);
fileList.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
fileList.setSelector(android.R.drawable.screen_background_light_transparent);
fileList.setOnItemClickListener(this);
// Set up button listeners
ImageButton dirup = (ImageButton) root.findViewById(R.id.explorer_up);
dirup.setOnClickListener(this);
Button but = (Button) root.findViewById(R.id.explorer_ok);
but.setOnClickListener(this);
but = (Button) root.findViewById(R.id.explorer_cancel);
but.setOnClickListener(this);
}
/** First time load with files in path */
private void loadList() {
File[] finalList;
try {
finalList = FileHelper.getFileList(path, showHidden);
} catch (IOException e) {
Log.e(TAG, e.getMessage(), true);
return;
}
FileExplorerAdapter list = (FileExplorerAdapter) fileList.getAdapter();
// No adapter set yet
if (list == null) {
// Java's way of life... most stupid thing ever
List<File> aux = new ArrayList<File>();
aux.addAll(Arrays.asList(finalList));
FileExplorerAdapter adapter = new FileExplorerAdapter(context,
aux);
fileList.setAdapter(adapter);
} else { // Modify adapter
list.clear();
list.addAll(finalList);
list.notifyDataSetChanged();
}
}
public void show() {
loadList();
showAtLocation(Gravity.CENTER, 0, 0);
}
@Override
public void run() {
show();
}
/** Set path to show */
public void setPath(String path) {
this.path = new File(path);
}
/** Show or not hidden files */
public void showHidden(boolean show) {
showHidden = show;
}
/** Refresh the list with current set path */
public void refresh() {
loadList();
}
@Override
public void onClick(View v) {
// Cannot use a switch/case...
int id = v.getId();
if (id == R.id.explorer_up) {
dirUp();
} else if (id == R.id.explorer_ok) {
ok();
} else if (id == R.id.explorer_cancel) {
//cancel();
}
}
/** Called when "explorer_up" button is clicked */
public void dirUp() {
File newPath = path.getParentFile();
if (newPath != null) {
path = newPath;
loadList();
}
}
/** Called when "explorer_ok" button is clicked */
public void ok() {
if (selected == null) {
Log.d(TAG, "Nothing selected");
} else {
Log.d(TAG, selected.getPath());
}
}
@Override
public void onItemClick(AdapterView<?> adapter, View v, int pos, long id) {
Log.d(TAG, "onItemClick");
selected = (File) fileList.getItemAtPosition(pos);
}
}
最后是弹出窗口的布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="vertical" >
<TextView
android:id="@+id/explorer_title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical|center_horizontal"
android:layout_margin="8dp"
android:ellipsize="marquee"
android:text="@string/explorer_title"
android:textColor="#ffffffff"
android:textSize="16dp" />
<ListView
android:id="@+id/explorer_list"
android:layout_width="fill_parent"
android:layout_height="400dp"
android:layout_margin="8dp" >
</ListView>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="8dp"
android:orientation="horizontal" >
<ImageButton
android:id="@+id/explorer_up"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:src="@drawable/dirup_icon"
android:onClick="dirUp" />
<Button
android:id="@+id/explorer_ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:text="@string/ok"
android:textSize="16dp" />
<Button
android:id="@+id/explorer_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:text="@string/cancel"
android:textSize="16dp" />
</LinearLayout>
</LinearLayout>
此实现的唯一问题是this