فصل نافذة النافذة المنبثقة Android
-
30-09-2019 - |
سؤال
لدي نافذة منبثقة تعرض عند النقر فوق عنصر في نشاط القائمة. المشكلة هي أن المفتاح الخلفي لا يغلقه. حاولت اللحاق بالمفتاح الخلفي في نشاط القائمة الخاص بي ، لكنه لا يسجله ... ثم حاولت تسجيل onKeyListener إلى العرض الذي أمرره إلى نافذتي المنبثقة. مثله:
pop.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
boolean res=false;
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
// do something on back.
Log.e("keydown","back");
if (pw.isShowing()) {
Log.e("keydown","pw showing");
pw.dismiss();
res = true;
}
} else {
res = false;
}
return res;
}
});
الذي ينتقل إلى نافذة منبثقة مثل هذا:
pw = new PopupWindow(
pop,
240,
70,
true);
لكن هذا المستمع لا يطلق النار. هل بإمكانك مساعدتي؟ أنا خارج الأفكار :)
المحلول
وذلك لأن نافذة المنبثقة لا تستجيب لأحداث OnTouch أو Onkey ما لم يكن لها خلفية! = NULL. تحقق من بعض الرمز الذي كتبته للمساعدة في هذا. في الحالة الأساسية يمكنك الاتصال PopupWindow#setBackgroundDrawable(new BitmapDrawable())
لإجبارها على التصرف بالطريقة التي تتوقعها. لن تحتاج إلى مستمع Onkey الخاص بك. قد تحتاج أيضًا إلى الاتصال PopupWindow#setOutsideTouchable(true)
إذا كنت تريد أن تختفي عندما ينقر المستخدم خارج حدود النافذة.
الإجابة الباطنية الممتدة:
السبب في أن الخلفية لا يمكن أن تكون لاغية هو ما يحدث PopupWindow#preparePopup
. إذا اكتشف background != null
يخلق مثيلًا PopupViewContainer
والمكالمات setBackgroundDrawable
على ذلك ويضع عرض المحتوى الخاص بك فيه. PopupViewContainer
هو أساسا FrameLayout
التي تستمع لأحداث اللمس و KeyEvent.KEYCODE_BACK
حدث لرفض النافذة. إذا كانت الخلفية == NULL ، فهي لا تفعل أيًا من ذلك وتستخدم فقط عرض المحتوى الخاص بك. يمكنك ، كبديل للاعتماد على PopupWindow
للتعامل مع ذلك ، قم بتوسيع جذرك ViewGroup
للتصرف بالطريقة التي تريدها.
نصائح أخرى
تفعل حسب ما يليها تعمل بشكل جيد:
PopupWindow pw;
LayoutInflater inflater = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.weight_popup, (ViewGroup)findViewById(R.id.linlay_weight_popup));
pw = new PopupWindow(layout,LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT, true);
pw.setBackgroundDrawable(new BitmapDrawable());
pw.setOutsideTouchable(true);
pw.showAsDropDown(btnSelectWeight);
بالنسبة للمشاريع الجديدة ، من الأفضل استخدامها
popupWindow.setBackgroundDrawable(new ColorDrawable());
بدلاً من
popupWindow.setBackgroundDrawable(new BitmapDrawable());
كما تم إهمال Bitmapdrawable. أيضا ، هو أفضل من القابلة للتشكيل في هذه الحالة. لقد لاحظت أنه عندما يكون popupwindow مستطيلًا مع زوايا مستديرة ، يملأ زوايا القابلة للرسائل السوداء.
الحل البسيط حقًا هو كتابة pw.setfocusable (صحيح) ، ولكن ربما لا تريد القيام بذلك لأن النشاط الخريطة لن تتعامل مع الأحداث التي تعمل باللمس.
الحل الأفضل هو تجاوز المفتاح الخلفي ، على سبيل المثال:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// Override back button
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (pw.isShowing()) {
pw.dismiss();
return false;
}
}
return super.onKeyDown(keyCode, event);
}
حظا طيبا وفقك الله!
للباحثين الجدد, ، كما إنشاء ملف new BitmapDrawable
غير مسموح به الآن (The constructor BitmapDrawable() is deprecated
) ، بحيث عليك تغييره إلى أ new ShapeDrawable()
, ، حتى تتغير:
pw.setBackgroundDrawable(new BitmapDrawable());
إلى :
pw.setBackgroundDrawable(new ShapeDrawable());
وسيكون العمل كله مثل:
PopupWindow pw;
LayoutInflater inflater = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.weight_popup, (ViewGroup)findViewById(R.id.linlay_weight_popup));
pw = new PopupWindow(layout,LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT, true);
pw.setOutsideTouchable(true);
pw.setBackgroundDrawable(new ShapeDrawable());
pw.setTouchInterceptor(new OnTouchListener() { // or whatever you want
@Override
public boolean onTouch(View v, MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_OUTSIDE) // here I want to close the pw when clicking outside it but at all this is just an example of how it works and you can implement the onTouch() or the onKey() you want
{
pw.dismiss();
return true;
}
return false;
}
});
pw.showAtLocation(layout, Gravity.CENTER, 0, 0);
فقط استخدم هذا
mPopupWindow.setBackgroundDrawable(new BitmapDrawable(null,""));
الذي لم يتم إهماله. كنت أتجنب جديد من القابلة للعلاج () لأنها ستجعلها ببطء حيث تحاول رسم شكل عندما تحتاج الشاشة إلى إعادة رسمها.
آمل أن يكون هذا هو المساعدة لك
pw.setTouchInterceptor(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if (event.getAction() == MotionEvent.ACTION_DOWN) {
pw.dismiss();
}
return true;
}
});
تحتاج إلى إضافة setBackgroundDrawable(new BitmapDrawable())
من اجلك PopupWindow
.
private void initPopupWindow() {
// TODO Auto-generated method stub
View view = getLayoutInflater().inflate(R.layout.main_choice, null);
ListView main_menu_listview = (ListView) view.findViewById(R.id.main_menu_listview);
ShowMainChoice madapter = new ShowMainChoice(context);
main_menu_listview.setAdapter(madapter);
int width = (int)getWindowManager().getDefaultDisplay().getWidth()/2;
popupWindow = new PopupWindow(view, width,WindowManager.LayoutParams.WRAP_CONTENT);
popupWindow.setBackgroundDrawable(new BitmapDrawable());//this is important,如果缺少这句将导致其他任何控件及监听都得不到响应
popupWindow.setOutsideTouchable(true);
popupWindow.setFocusable(true);
main_menu_listview.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
// TODO Auto-generated method stub
Log.e("++++++>", arg2+"");
}
});
}
هذه المشكلة هي popupwindow 底层 消息 机制 机制 决定 , , 因为 它 阻塞式 的。
pw.setBackgroundDrawable(new ColorDrawable());
يجب أن يكتبها من قبل setContentView
هذا يعمل بالنسبة لي.