如何在Android中创建一个弹出视图,类似于Facebook评论?

24

我在想是否有人知道如何创建类似 Facebook Android 应用程序中评论弹出视图的弹出框。

这就是我的意思:

enter image description here

除了您可以拖动以关闭它的句柄之外,它是原生的 Android UI 控件还是 Facebook 自己实现的?


我遇到了类似的问题,需要创建评论详细视图并向右或向下拖动以关闭视图并在评论视图上打开点赞视图。你能分享一下你是如何通过视图和视图组实现的代码吗?因为这似乎无法通过对话框或弹出窗口来实现。 - YasirSE
24
你选择截屏的谈话很有趣。 - Mike
5个回答

57
创建类似弹出视图(popover view)的最佳方法是使用PopupWindow,因为您可以将PopUpWindow放在任何特定视图位置(或者屏幕中心/顶部/底部)。您也可以使用DialogFragment实现相同的UI,但无法定位到特定的视图位置。

我在这里提供了完整可工作的代码https://gist.github.com/libinbensin/67fcc43a7344758390c3

步骤1:创建自定义布局,例如Facebook的布局有一个带有Header TextViewListViewEditText的布局。

步骤2:将布局设置给PopupWindow

填充布局进行设置

LayoutInflater layoutInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View inflatedView = layoutInflater.inflate(R.layout.fb_popup_layout, null,false);

这个 Layout 包含一个 ListView,所以在这个布局中找到 ListView 并填充数据。你可以在这里使用自己的视图。

ListView listView = (ListView)inflatedView.findViewById(R.id.commentsListView);
listView.setAdapter(new ArrayAdapter<String>(TryMeActivity.this,
        R.layout.fb_comments_list_item, android.R.id.text1,contactsList));

现在,创建一个具有特定高度和宽度的PopupWindow实例。我倾向于根据设备设置大小。
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);

popWindow = new PopupWindow(inflatedView, size.x - 50,size.y - 500, true );

设置弹出窗口的focusability(焦点可获取性)。

popWindow.setFocusable(true);

当在弹出区域以外触摸时,使其可以被触摸关闭弹出窗口

popWindow.setOutsideTouchable(true);

现在,使用可绘制对象为PopupWindow设置背景。该可绘制对象具有带有圆角半径矩形形状
  popWindow.setBackgroundDrawable(getResources().getDrawable(R.drawable.fb_popup_bg));

最后,在所需的位置显示PopupWindow。我让它在屏幕底部显示,带有一些X和Y位置

popWindow.showAtLocation(v, Gravity.BOTTOM, 0,150);  // 0 - X postion and 150 - Y position

您还可以设置一个Animation,以在PopUpWindow出现和消失时使用。

popWindow.setAnimationStyle(R.anim.animation); // call this before showing the popup

enter image description here


非常好!你让我朝着正确的方向前进了 - 尽管最终我使用了View和ViewGroup而不是PopupWindow。 - David Xu
1
非常好的例子,谢谢。我有一个快速问题,如果我想要制作某种类型的线条或连接器到锚点,你会建议如何做呢?(请参见我的图像,这是右上角连接到锚点的视觉示例 - http://i422.photobucket.com/albums/pp308/P_G_Mac/connected%20example.png) - PGMacDesign
@Silmarilos,你想出了办法吗? - Faser
很遗憾,我没有。最终我只是手动使用了marginTop方法,但在平板电脑上它并不能很好地扩展 :( - PGMacDesign

7

编辑:

实际上,尽管我使用了DialogFragment,但我非常确定他们的弹出框并没有使用DialogFragment(甚至根本没有使用对话框!)。原因是调整大小的功能。如果您需要这样的功能,则无法使用DialogFragment。您只需向布局添加一个新视图即可。看起来Facebook还有另一个视图,它位于您的墙和虚假弹出窗口之间,略微半透明,并侦听点击以关闭该视图。构建这样的东西需要一些实际的努力和时间,所以我不会为您创建这个。如果您对此有任何疑问,请告诉我,我可能可以指导您找到您想要的解决方案。

原文:

我为您编写了弹出窗口:

public class MyActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (savedInstanceState == null) {
            F1.newInstance().show(getFragmentManager(), null);
        }
    }

    public static class F1 extends DialogFragment {

        public static F1 newInstance() {
            F1 f1 = new F1();
            f1.setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme_DeviceDefault_Dialog);
            return f1;
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

            // Remove the default background
            getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

            // Inflate the new view with margins and background
            View v = inflater.inflate(R.layout.popup_layout, container, false);

            // Set up a click listener to dismiss the popup if they click outside
            // of the background view
            v.findViewById(R.id.popup_root).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    dismiss();
                }
            });

            return v;
        }
    }
}

popup_layout.xml:

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clickable="true"
    android:id="@+id/popup_root">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="72dp"
        android:layout_marginBottom="72dp"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        android:padding="20dp"
        android:clickable="true"
        android:background="@drawable/dialog_background">

        <TextView
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:textColor="#000"
            android:text="Content goes here!" />

    </FrameLayout>

</FrameLayout>

同时,还需要编辑dialog_background.xml(存放在res/drawable目录下):

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
    <solid android:color="#FFF" />
    <corners android:topLeftRadius="20dp" android:topRightRadius="20dp"
         android:bottomLeftRadius="20dp" android:bottomRightRadius="20dp"/>
    <stroke android:color="#7F7F7F" android:width="1dp" />
</shape>

它看起来像这样:

输入图像描述

只需添加您的视图内容,就可以开始使用了!


这是目前为止最好的答案,但我想问一下,有没有办法使对话框不覆盖ActionBar?具体来说,有没有办法让覆盖部分仅覆盖它所显示的Fragment? - David Xu
你不能使用对话框来实现,我认为你只能通过在FrameLayout的顶部添加一个带有半透明背景的普通片段来“伪造”对话框,该片段位于ActionBar下方。当用户点击外部时,只需从布局中删除该片段即可。这样做还可以获得更多的灵活性,您可以控制视图的大小等。 - Bradley Campbell

1

0

这似乎是 Facebook 构建的自定义组件。它不是标准的 Android 组件。您可以尝试通过从 Dialog Fragment 派生来实现它。


你确定它是Dialog Fragment吗?它似乎有点复杂,不可能只是从一个Dialog Fragment派生出来的。 - David Xu
这并没有提供问题的答案。如果您想对作者进行批评或请求澄清,请在他们的帖子下留言。 - Trilarion

-1

看起来最简单的方法是使用一个带有透明(或在这种情况下半透明)背景的片段。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接