我想在我的代码中显示一个弹出窗口,这样无论我在屏幕上的哪个位置触摸,弹出窗口都会显示在我触摸的位置的正上方。不确定,如何实现这一目标。这是我当前的弹出窗口代码:
LayoutInflater inflater = (LayoutInflater) getApplicationContext().getSystemService(LAYOUT_INFLATER_SERVICE);
View customView = inflater.inflate(R.layout.popup,null);
final PopupWindow popupWindow = new PopupWindow(
customView,
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
// Set an elevation value for popup window
// Call requires API level 21
if(Build.VERSION.SDK_INT>=21){
popupWindow.setElevation(5.0f);
}
final TextView placename = (TextView) customView.findViewById(R.id.popup_id) ;
Button closeButton = (Button) customView.findViewById(R.id.directions);
placename.setText(place.getName());
popupWindow.setBackgroundDrawable(new BitmapDrawable());
popupWindow.setOutsideTouchable(true);
// Set a click listener for the popup window close button
closeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// Dismiss the popup window
popupWindow.dismiss();
}
});
popupWindow.setFocusable(true);
popupWindow.showAtLocation(mapInsideContainer, Gravity.CENTER, 0, 0);
popupWindow.showAsDropDown(customView);
这是我的popup.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="@android:color/background_light">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_margin="1dp"
android:background="@android:color/white">
>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_margin="20dp">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#000000"
android:id="@+id/popup_id" />
<Button
android:id="@+id/directions"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@color/black_overlay"
android:textColor="@android:color/white"
android:text="Directions" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
目前,由于Gravity.CENTER,它显示在屏幕中央,但我想将它显示在我在屏幕上动态触摸的位置上方。有任何想法吗?感谢
奖励积分如果您可以引导我创建一个聊天气泡,如弹出窗口顶部带有标题,底部带有“位置”按钮,点击屏幕上的位置点击气泡指针
答案 0 :(得分:1)
这就是我所做的,希望帮助你
customView.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
popupWindow.showAtLocation(getWindow().getDecorView(), Gravity.NO_GRAVITY, (int)event.getX(), (int)event.getY() - customView.getMeasuredHeight());
并覆盖public boolean onTouchEvent(MotionEvent event)
@Override
public boolean onTouchEvent(MotionEvent event) {
popup(event);
return super.onTouchEvent(event);
}
编辑: 我的写作跟随,它为我工作。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
popup(event);
return super.onTouchEvent(event);
}
private void popup(MotionEvent event) {
LayoutInflater inflater = (LayoutInflater) getApplicationContext().getSystemService(LAYOUT_INFLATER_SERVICE);
View customView = inflater.inflate(R.layout.popup,null);
final PopupWindow popupWindow = new PopupWindow(
customView,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT);
// Set an elevation value for popup window
// Call requires API level 21
if(Build.VERSION.SDK_INT>=21){
popupWindow.setElevation(5.0f);
}
final TextView placename = (TextView) customView.findViewById(R.id.popup_id) ;
Button closeButton = (Button) customView.findViewById(R.id.directions);
placename.setText("Name");
popupWindow.setBackgroundDrawable(new BitmapDrawable());
popupWindow.setOutsideTouchable(true);
// Set a click listener for the popup window close button
closeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// Dismiss the popup window
popupWindow.dismiss();
}
});
// popupWindow.setFocusable(true);
popupWindow.setOutsideTouchable(true);
customView.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
popupWindow.showAtLocation(getWindow().getDecorView(), Gravity.NO_GRAVITY, (int)event.getX(), (int)event.getY() - customView.getMeasuredHeight());
getWindow().getDecorView().setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
});
}
}
activity_main.xml中
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/parent"
android:background="@color/colorAccent"
android:fitsSystemWindows="true">
</android.support.constraint.ConstraintLayout>
答案 1 :(得分:0)
尝试创建透明的活动,而不是使用PopupWindow,类似于this。
然后,您可以为聊天气泡创建自定义绘图(因为气泡指针需要位于不同的位置,具体取决于用户点击的位置)。覆盖onTouchEvent()并获取用户触摸的坐标,然后启动透明活动并将其传递给意图中的坐标,以便您可以将气泡视图放置在适当的位置。
这会增加额外的开销,因为您正在启动一个新的Activity,但它可以让您充分发挥自己想要的自定义外观和行为的能力。
这是一些细节。当我想要自定义弹出菜单时,这就是我所做的。
对于透明活动,创建一个新活动并在清单中为其指定一个主题:
<activity
android:name=".PopupActivity"
android:theme="@style/Transparent" />
在styles.xml中:
<style name="Transparent" parent="Theme.AppCompat.NoActionBar">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@color/translucent</item>
</style>
您可以将@color/translucent
定义为完全透明,我会在其中添加一些灰色,以便在弹出窗口显示时,下面的视图显示为暗淡。
在活动的布局中:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_popup"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary"
android:layout_margin="60dp">
这里我使用的是RelativeLayout,但你可以使用你想要的任何布局,重要的是边距。现在活动看起来像这样,背景活动在这一背后可见:
接下来,您将使用触摸坐标动态更改边距,使矩形显示在您想要的任何位置。
我们需要知道屏幕顶部的屏幕大小和密度以及状态栏的高度,因此在主要活动的onCreate()方法中,添加:
//Determine the screen dimensions and density
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
screenWidth = metrics.widthPixels;
screenHeight = metrics.heightPixels;
screenDensity = metrics.density;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
int statusBarHeight = (int) (24 * density);
if (resourceId > 0) {
statusBarHeight = getResources().getDimensionPixelSize(resourceId);
}
这些值不会改变,因此将它们存储在静态变量中,以便其他类可以在需要时获取它们。
现在,在透明活动的onCreate()方法中,根据触摸事件坐标计算边距:
int popupSize = 100;
int rMargin, lMargin, tMargin, bMargin;
lMargin = xCoord - popupSize;
rMargin = screenWidth - xCoord - popupSize;
tMargin = yCoord - popupSize;
bMargin = screenHeight - yCoord - popupSize - statusBarHeight;
RelativeLayout layout = (RelativeLayout) findViewById(R.id.activity_popup);
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) layout.getLayoutParams();
params.setMargins(lMargin, tMargin, rMargin, bMargin);
layout.setLayoutParams(params);
这会创建一个以触摸坐标为中心的正方形。例如,给定x = 700和y = 1500,我得到:
对于x = 150和y = 200,我得到:
你可以看到,在这种情况下,如果坐标太靠近边缘,你将获得一个负边距,并将裁剪正方形。需要更多的数学来纠正这一点。
我要做的是将屏幕区域划分为四个象限并计算触摸事件所在的象限。然后,例如,如果触摸位于左上象限,则将方块的左上角与触摸对齐坐标。这样,屏幕边缘永远不会裁剪正方形。
就创建带指针的气泡而言,制作4个气泡的自定义绘图,每个绘制指针位于不同的角落。然后,根据触摸事件的象限,加载适当的drawable,使指针始终在正确的方向。
这篇文章虽然有点太长了。