Отображение в верхней части панели действий
Есть ли способ визуализации представления поверх панели действий? Я хочу создать небольшой наконечник, который указывает пользователю на элемент в панели действий. Я знаю, что a Toast
с заданным представлением будет отображаться над панелью действий. Кто-нибудь знает, как это сделать с представлением?
Я попытался использовать FrameLayout
с layout_gravity="top"
и раздуть представление, а затем добавить его в макет текущей работы.
Я ценю вас заранее.
Edit:
Вот образ того, что я думал:
![enter image description here]()
Edit:
Возможно, требуется более подробная информация. Я ищу способ или выяснить, возможно ли даже добавить представление в иерархию представления активности, чтобы она была последней.
Подобно CSS, мне нужен более высокий порядок z-index для этого конкретного вида (синий плавающий ящик на изображении), так что он будет отображаться поверх области Action Bar в действии. Представление никоим образом не связано с панелью действий, оно просто нарисовано поверх него.
Ответы
Ответ 1
После того как я боролся с этим сам довольно некоторое время, вот решение (протестировало это - работало хорошо):
Общие шаги:
- Создать представление оболочки
- Отсоедините дочерние элементы экрана, поместите обертку и прикрепите дочерние элементы
- Нажать содержимое детям
- Управление оболочкой поможет вам точно контролировать панель действий и содержимое под ним все вместе.
- Теперь, используя обертку, вы можете добавить "братья" в панель действий/главную область. Этот брат - это то, что вы описали в своем образе.
Посмотрим на код.
Сначала создайте метод, который поможет создать представление оболочки. оболочка будет помещена между всем экраном и содержимым вашего приложения. будучи ViewGroup, вы можете в дальнейшем полностью контролировать его содержимое.
private ViewGroup setContentViewWithWrapper(int resContent) {
ViewGroup decorView = (ViewGroup) this.getWindow().getDecorView();
ViewGroup decorChild = (ViewGroup) decorView.getChildAt(0);
// Removing decorChild, we'll add it back soon
decorView.removeAllViews();
ViewGroup wrapperView = new FrameLayout(this);
// You should set some ID, if you'll want to reference this wrapper in that manner later
//
// The ID, such as "R.id.ACTIVITY_LAYOUT_WRAPPER" can be set at a resource file, such as:
// <resources xmlns:android="http://schemas.android.com/apk/res/android">
// <item type="id" name="ACTIVITY_LAYOUT_WRAPPER"/>
// </resources>
//
wrapperView.setId(R.id.ACTIVITY_LAYOUT_WRAPPER);
// Now we are rebuilding the DecorView, but this time we
// have our wrapper view to stand between the real content and the decor
decorView.addView(wrapperView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
wrapperView.addView(decorChild, decorChild.getLayoutParams());
LayoutInflater.from(this).inflate(getActivityLayout(),
(ViewGroup)((LinearLayout)wrapperView.getChildAt(0)).getChildAt(1), true);
return wrapperView;
}
Теперь помешайте регулярному Activity созданию и вместо setContentView, используйте метод, который мы создали.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// DON'T CALL `setContentView`,
// we are replacing that line with this code:
ViewGroup wrapperView = setContentViewWithWrapper(R.layout.activity_layout);
// Now, because the wrapper view contains the entire screen (including the notification bar
// which is above the ActionBar) I think you'll find it useful to know the exact Y where the
// action bar is located.
// You can use something like that:
ViewGroup actionBar = (ViewGroup)((LinearLayout)wrapperView.getChildAt(0)).getChildAt(0);
int topOffset = actionBar.getTop();
// Now, if you'll want to add a view:
// 1. Create new view
// 2. Set padding top - use "topOffset"
// 3. Add the view to "wrapperView"
// 4. The view should be set at front. if not - try calling to "bringToFront()"
}
Что об этом.
Примечания
- Я использовал Android-иерархию Android, чтобы понять, что такое правильная иерархия. (не догадывались те индексы
0
и 1
)
- Если вы используете какой-либо ящик меню в своей деятельности, вам может потребоваться настроить его немного по-другому, поскольку ящики уже создают эту оболочку для вас.
- Я многому научился, посмотрев эту отличную библиотеку
РЕДАКТИРОВАТЬ: Обратитесь к @CristopherOyarzúnAltamirano Ответ для дальнейшей поддержки в новых версиях Android
Удачи!
Ответ 2
Я пытался добиться чего-то другого, но мне было нужно решение, подобное этому. Мне нужно было нарисовать непрозрачный слой, покрывающий весь экран, даже панель действий - вроде как диалог. Я сделал так:
ViewGroup vg = (ViewGroup)(getWindow().getDecorView().getRootView());
vg.addView(myNewView, params);
это можно использовать для рисования чего угодно в любом месте экрана.
Ответ 3
Существует гораздо более простой способ добиться этого. ActionBar имеет свой макет в классе ActionBarContainer, который просто наследуется от FrameLayout. Итак, чтобы отобразить что-то над ActionBar, вам нужно получить ссылку на ActionBarContainer и добавить в него собственный пользовательский вид. Вот код
int abContainerViewID = getResources().getIdentifier("action_bar_container", "id", "android");
FrameLayout actionBarContainer = (FrameLayout)findViewById(abContainerViewID);
LayoutInflater myinflater = getLayoutInflater();
View customView = myinflater.inflate(R.layout.yourCustomeViewLayout, null);
actionBarContainer.addView(customView);
Ответ 4
Я нашел это обходное решение на основе ответа @Sean:
//This is for Jelly, ICS, Honeycomb
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2){
LayoutInflater.from(this).inflate(resContent, (ViewGroup)((LinearLayout)wrapperView.getChildAt(0)).getChildAt(1), true);}
//This is for KitKat and Jelly 4.3
else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){
LayoutInflater.from(this).inflate(resContent, (ViewGroup) (((ViewGroup) wrapperView.getChildAt(0)).getChildAt(0)), true);}
//This is for Ginger
else{
LayoutInflater.from(this).inflate(resContent, (ViewGroup) ((LinearLayout)((FrameLayout) wrapperView.getChildAt(0)).getChildAt(0)).getChildAt(1), true);}
Ответ 5
Попробуйте использовать ActionBar.setCustomView(). Это единственный способ изменить внешний вид этой области экрана. Вы не можете вставить "Вид" в область "выше" ActionBar, потому что эта область в основном контролируется системой. С другой стороны, вы можете предоставить свой собственный макет для него.
Если вы более подробно объясните, что вы пытаетесь сделать, у респондентов могут быть несколько лучших дизайнерских идей.
Ответ 6
https://github.com/michaelye/EasyDialogDemo
см. демонстрацию выше, это может помочь вам
dialog.setLocation(new location[])//point in screen
вы можете установить местоположение [] самостоятельно.
Ответ 7
Я нашел гораздо более простой способ сделать это.
Я просто применил android: translationZ = "10dp" к представлению, которое мне нужно покрыть панель действий.
Я выбрал 10dp, но на самом деле это может быть все, что вы хотите, если оно превосходит высоту панели действий
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:translationZ="10dp"
android:src="@drawable/potatoe" />
Кроме того, не беспокойтесь о следующем предупреждении в студии Android:
"translationZ не может использоваться с API < 21".
Он будет проигнорирован, но вам все равно, потому что панель инструментов не должна покрывать ваше представление API-интерфейсом ниже 21.
Ответ 8
Используйте android:actionLayout
в файле menu.xml.
<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_id"
android:title="@string/menu_string_to_show"
android:icon="@drawable/ic_menu_icon_name"
android:showAsAction="always"
android:actionLayout="@layout/action_button_foo" /></menu>
Затем создайте свой макет action_button_foo.xml:
<?xml version="1.0" encoding="utf-8"?><TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/menu_string_to_show"
android:drawableLeft="@drawable/ic_menu_icon_name"
android:background="@drawable/bg_btn_action_bar"
android:clickable="true" />
Для обработки щелчка сделайте следующее:
@Overridepublic boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.my_menu, menu);
final MenuItem item = menu.findItem(R.id.menu_id);
item.getActionView().setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onOptionsItemSelected(item);
}
});
return super.onCreateOptionsMenu(menu);}
Что если:)
Ответ 9
(Ссылка: http://www.vogella.com/articles/AndroidActionBar/article.html)
Пользовательские представления в ActionBar
Вы также можете добавить пользовательский вид в ActionBar
. Для этого вы используете метод setCustomView
для класса ActionView
. Вы также должны включить отображение пользовательских представлений с помощью метода setDisplayOptions()
, передав флаг ActionBar.DISPLAY_SHOW_CUSTOM
.
Например, вы можете определить файл макета, содержащий элемент EditText
.
<?xml version="1.0" encoding="utf-8"?>
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/searchfield"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:inputType="textFilter" >
Этот макет может быть назначен ActionBar
с помощью следующего кода. Код примера позволяет подключить слушателя к пользовательскому представлению.
package com.vogella.android.actionbar.customviews;
import android.app.ActionBar;
import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar = getActionBar();
// add the custom view to the action bar
actionBar.setCustomView(R.layout.actionbar_view);
EditText search = (EditText) actionBar.getCustomView().findViewById(R.id.searchfield);
search.setOnEditorActionListener(new OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
Toast.makeText(MainActivity.this, "Search triggered",
Toast.LENGTH_LONG).show();
return false;
}
});
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM
| ActionBar.DISPLAY_SHOW_HOME);
}
}