在的ListView Android的PopupWindowListView、Android、PopupWindow

2023-09-06 16:16:04 作者:装逼卖萌无所不能

有一个简单的例子或教程,如何把一个的ListView (正从 BaseAdapter 通过XML值解析器)在 PopupWindow Android中?

Is there a simple example or tutorial, how to put a ListView (getting the value from BaseAdapter through XML parser) in PopupWindow in Android?

推荐答案

您可能要检查ListPopupWindow

这是我做的:

PopupWrapper 类只是包装 PopupWindow 更友好的类中:

PopupWrapper class just wraps PopupWindow inside a more friendly class:

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);
    }
}

档案总管类是使用的例子 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 mymail@blablabla.eu
 * 
 */
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);
    }
}

和最后的布局弹出窗口:

And finally the layout for the popup window:

<?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