показать вид поверх панели действий

есть ли способ отобразить представление поверх панели действий? Я хочу создать небольшое окно подсказки, которое укажет пользователю на элемент в панели действий. Я знаю, что Toast с заданным видом будет отображаться над панелью действий. Кто-нибудь знает, как это сделать с видом?

Я попытался с помощью FrameLayout С layout_gravity="top" и раздувание представления, а затем добавление его в макет выполняемого действия.

Я ценю вас заранее.

редактировать: Вот образ того, о чем я думал.: enter image description here

редактировать: Возможно, потребуется больше деталей. Я ищу способ или выяснить, можно ли даже добавить представление в иерархию представлений действия, чтобы оно отображалось последним.

подобно CSS, я хочу более высокий порядок Z-индекса для этого конкретного вида (синее плавающее поле на изображении), так что он будет отображаться поверх панели действий регион в деятельности. Вид никоим образом не связан с панелью действий, он просто нарисован поверх нее.

9 ответов


после борьбы с ним сам довольно долгое время, вот решение (протестировано-работает хорошо):

общие шаги:

  1. создать вид оболочки
  2. отсоедините детей просмотра экрана, поместите обертку и прикрепите детей
  3. надуть содержание для детей
  4. управление оберткой поможет вам точно контролировать панель действий и содержимое под ней все вместе.
  5. теперь, используя обертка, вы можете добавить "братья" в actionbar/основную область. Этот брат-именно то, что ты описал в своем образе.

давайте посмотрим код.

сначала создайте метод, который поможет создать представление-оболочку. обертка будет помещена между всем экраном и содержимым вашего приложения. быть 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;
    }

теперь, мешают регулярные активность создание, и вместо использования 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-viewer чтобы понять, что такое правильная иерархия. (не угадал те 0 и 1 индексы)
  • если вы используете какой-то ящик меню в своей деятельности, вам, возможно, придется настроить его немного по-другому, так как ящики уже создаются эта обертка для тебя!--10-->
  • Я многому научился, глядя на это большая библиотека

EDIT: см. @CristopherOyarzúnAltamirano ответ для дальнейшей поддержки на более новых версиях Android

удачи!


Я пытался достичь чего-то еще, но мне нужно было решение, подобное этому. Мне нужно нарисовать непрозрачный слой, покрывающий весь экран, даже панель действий-что-то вроде диалога. Я сделал так:

ViewGroup vg = (ViewGroup)(getWindow().getDecorView().getRootView());
vg.addView(myNewView, params);

Это можно использовать для рисования чего угодно в любом месте экрана.


существует гораздо более простой способ достичь этого. 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);

Я нашел это обходное решение на основе @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);}

Я нашел гораздо более простой способ сделать это. Я только что подал заявку android: translationZ= "10dp" к виду, который мне нужно охватить панель действий.

Я выбрал 10dp, но на самом деле это может быть все, что вы хотите, пока он превосходит высоту actionbar

<ImageView
      android:layout_width="100dp"
      android:layout_height="100dp"
      android:translationZ="10dp"
      android:src="@drawable/potatoe" />

кроме того, не беспокойтесь о следующем предупреждении Android studio:

"translationZ нельзя использовать с API

будет игнорируется, но вам все равно, потому что панель инструментов не должна покрывать ваше представление API, уступающими 21.


попробуйте использовать ActionBar.setCustomView(). Это единственный способ изменить внешний вид этой области экрана. Вы не можете вставить вид в область "выше" панели действий, потому что эта область в основном контролируется системой. С другой стороны, ты!--1-- > can предоставить свой собственный макет для него.

Если вы объясните более подробно, что вы пытаетесь сделать, у респондентов могут быть лучшие дизайнерские идеи.


https://github.com/michaelye/EasyDialogDemo

посмотреть демо выше,это может помочь вам

dialog.setLocation(new location[])//point in screen

вы можете установить местоположение[] самостоятельно.


использовать android:actionLayout в вашем меню.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);}

это если :)


(ссылка: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);
}
}