2013-03-07 132 views
36

是否有一種方法可以在操作欄頂部顯示視圖?我想創建一個小提示框,將用戶指向操作欄中的項目。我知道具有設置視圖的Toast將顯示在操作欄上方。有誰知道如何做到這一點與視圖?在操作欄頂部顯示視圖

我試圖使用FrameLayoutlayout_gravity="top",並使視圖膨脹,然後將其添加到正在運行的活動的佈局。

我很感謝你提前。

編輯: 下面是我在想什麼的圖像: enter image description here

編輯: 也許需要一些更多的細節。我正在尋找一種方法,或者找出是否可以將視圖添加到活動的視圖層次結構中,以便最後呈現它。

與CSS類似,我想爲此特定視圖(圖像中的藍色浮動框)設置更高的Z-index順序,以便它將呈現在活動的操作欄區域之上。該視圖與Action Bar沒有任何關聯,只是簡單地將其放在頂部。

+0

你找到一個解決這個問題?我想現在在我的應用程序中執行相同的任務,但我在下面看不到任何相關答案。 – 2013-03-25 23:01:23

+0

@MM看看我的答案。剛添加它。 – Sean 2013-06-05 16:42:14

回答

21

與它自己掙扎了一段時間後,這裏的解決方案(測試了 - 工作好):

的一般步驟是:

  1. 創建包裝視圖
  2. 拆離屏幕查看兒童,放置包裝並附上兒童
  3. 將內容充滿兒童
  4. 控制包裝將幫助您精確控制操作欄及其下面的所有內容。
  5. 現在,使用包裝器,您可以將「兄弟」添加到操作欄/主區域。那個兄弟正是你在你的形象中描述的。

讓我們看看一些代碼。

首先,創建一個方法來幫助創建包裝視圖。包裝將被放置在整個屏幕和你的應用程序的內容之間。作爲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's hierarchy-viewer瞭解什麼是正確的層次結構。如果您正在使用某種在你的活動菜單抽屜(沒猜錯的01索引)
  • ,您可能需要配置它一點點不同,因爲抽屜已經創建的包裝爲你
  • 我通過觀察this great library

編輯學到了很多東西:參考@CristopherOyarzúnAltamirano回答進一步的支持在較新的Android版本

祝你好運!

+0

嘿男人。我在執行android 4.4的這個解決方案時遇到了一些問題。我有這個例外,有什麼想法嗎? com.android.internal.widget.ActionBarOverlayLayout不能轉換爲android.widget.LinearLayout。 – Dan1one 2013-11-22 06:44:32

+2

這是ICS和果凍的工作,但Ginger和Kitkat以不同的方式繪製層次結構。 – 2013-12-09 15:51:37

+0

@CristopherOyarzúnAltamirano是的。 – Sean 2013-12-09 16:19:23

0

在你的menu.xml文件中使用android:actionLayout

<?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);} 

那如果:)

+0

感謝您的快速回復!但我相信這是爲操作欄創建一個菜單項?我只想在操作欄上畫一個視圖。但是這個觀點不應該是行動欄的一部分,它是不響應的。 – lunaleaps 2013-03-07 19:22:30

+0

你的意思是什麼意見? – 2013-03-08 09:52:00

+0

這將是佈局文件和圖像背景中的TextView。如果你看看我的OP中添加的圖像,那將是浮動的藍色框 – lunaleaps 2013-03-08 14:31:12

1

嘗試使用ActionBar.setCustomView( )。這是改變屏幕區域外觀的唯一方法。您無法將視圖粘貼到ActionBar上方的區域,因爲該區域基本上由系統控制。另一方面,你可以提供你自己的佈局。

如果您更詳細地解釋您要做什麼,受訪者可能會有一些更好的設計思路。

+0

酷,我已經包含了我在想什麼的圖像。我看到Toasts可以有一個視圖集。我很想知道他們如何將他們的視圖呈現在操作欄的頂部。 – lunaleaps 2013-03-07 19:48:50

0

(參考:http://www.vogella.com/articles/AndroidActionBar/article.html
ActionBar
自定義視圖您還可以添加自定義視圖到ActionBar。爲此,您可以使用setCustomView方法來獲得ActionView類。您還必須通過輸入ActionBar.DISPLAY_SHOW_CUSTOM標誌,通過setDisplayOptions()方法啓用顯示自定義視圖。

例如,您可以定義包含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); 
} 
} 
+0

啊,好吧,據我所知,當我點擊操作欄,特別是「EditText」時,你正在添加一個「Toast」通知。我想知道更多關於如何在視覺上在視頻頂部呈現視圖/佈局。就像我知道Android如何創建視圖層次結構一樣。我如何在層次結構中插入一個最後呈現的視圖,以便從z-index排序或「將視圖帶到最前面」的意義上,它出現在操作欄的「上方」。或者甚至有可能?無論如何,感謝你的幫助Vishal。 – lunaleaps 2013-03-08 14:40:15

+0

所以你說的是你必須在使用setCustomView的時候在操作欄上插入一個自定義視圖。我認爲你必須去自定義操作欄。 – 2013-03-08 15:55:26

+0

更好的是你去自定義操作欄(創建你自己的操作欄)。你可以隨心所欲地做任何事情。 – 2013-03-08 16:34:09

5

我發現這個解決辦法基於@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);} 
+1

我用這種方法在Gingerbird設備上出現錯誤。我編輯它像這樣:LayoutInflater.from(this).inflate(resContent,(ViewGroup)((FrameLayout)decorChild),true); – 2014-06-17 10:48:54

14

還有一個更簡單的實現這種方式。 ActionBar將其佈局保存在僅從FrameLayout繼承的ActionBarContainer類中。因此,爲了在ActionBar上顯示某些內容,您需要獲取對ActionBarContainer的引用並將自己的自定義View添加到其中。這裏是代碼

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); 
29

我試圖實現別的東西,但我需要類似的解決方案。我需要繪製一個覆蓋整個屏幕的不透明層,甚至是操作欄 - 就像一個對話框。我這樣做是這樣的:

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

這可以用來在屏幕上的任何地方畫任何東西。

2

我發現了一個更簡單的方法來做到這一點。 我剛剛應用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