最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺析Android Dialog中setContentView()方法

 更新時間:2017年05月16日 08:46:53   作者:我想我會記得你  
本篇文章主要介紹了Android Dialog中setContentView()方法的相關(guān)知識。具有很好的參考價值。下面跟著小編一起來看下吧

概述

Dialog在Android中是一個很優(yōu)秀的工具。在使用Dialog時,我們一般都會自定義要顯示的內(nèi)容布局。Dialog自帶了三個方法來支持自定義內(nèi)容布局。

 public void setContentView (int layoutResID);
 public void setContentView (View view);
 public void setContentView (View view, ViewGroup.LayoutParams params);

這三個方法內(nèi)部的實現(xiàn)原理都是一樣的,只是其封裝深度不同而已。三個方法可以說分別照顧了不同定制深度的開發(fā)者。

setContentView()流程

直接查看Dialog的源代碼,如下圖1所示。

【圖1】

上圖中mWindow在Dialog類中的定義如下:

 import android.view.Window;
 Window mWindow;

那么,它從何而來呢?如下圖2所示。

【圖2】

由上圖2可知,在構(gòu)造Dialog對象時,這個mWindow的值也被確定。它由PolicyManager提供。再往下跟系統(tǒng)代碼。

makeNewWindow(Context)方法的實現(xiàn)如下:

  // The static methods to spawn new policy-specific objects
  public static Window makeNewWindow(Context context) {
   return sPolicy.makeNewWindow(context);
  }

還得繼續(xù)往下跟。

import com.andorid.policy.internal.policy.impl.Policy;
/**
 * {@hide}
 */
public class Policy implements IPolicy {
 //...

 public Window makeNewWindow(Context context) {
  return new PhoneWindow(context);
 }
}

到這,貌似就差不多看到盡頭了,原來我們調(diào)用的setContentView就是在這個PhoneWindow類中被實現(xiàn)的。繼續(xù)跟進。

import com.android.internal.policy.impl.PhoneWindow;
/**
 * Android-specific Window.
 * <p>
 * todo: need to pull the generic functionality out into a base class
 * in android.widget.
 */
public class PhoneWindow extends Window implements MenuBuilder.Callback {
 //...
}

setContentView(int)

這個方法的代碼實現(xiàn)如下圖3所示。

【圖3】

整個的實現(xiàn)流程乍一看還算簡單明了。我們傳入的布局參數(shù)最后就是被加載到上圖所示的那個 mContentParent 中的。這個mContentParent是一個ViewGroup類對象。

在上圖所示的代碼中第367行作了空判斷,可見這個對象的實例的創(chuàng)建與installDecor()方法有關(guān)系。這個方法的實現(xiàn)較為復(fù)雜,這里我們只看mContentParent的實例化過程。

【圖4】

這個generateLayout()方法的實現(xiàn)過程很繁雜。我們沒有必要去把每一行的代碼都看懂。只需要知道在它內(nèi)部是這樣創(chuàng)建mContentParent對象的就好了

,

。

最后會把這個contentParent作為結(jié)果返回即可。然后再回到圖3,在圖中所示代碼處第378行完成了將我們傳入的布局加載進系統(tǒng)容器中的操作。

setContentView(View)與setContentView(View, ViewGroup.LayoutParams)

這種方式設(shè)置內(nèi)容布局比較靈活。一般用于布局中有需要在Java代碼中做特殊操作的布局。其具體實現(xiàn)代碼如下圖5所示。

【圖5】

這個代碼,并沒什么特別的,它的目的都已經(jīng)明明白白的表現(xiàn)在代碼上了,就不再贅述了。

setContentView(View)無法設(shè)置布局尺寸的問題

使用setContentView(int)的方式時,可以直接通過在layout的根容器中指定寬、高來設(shè)置布局的尺寸。這里得注意,我指的是在根視圖中直接指定寬度多少像素,高度多少像素這種直白的寫法才可以控制布局的尺寸。若直接設(shè)為MATCH_PARENT,那么它的效果等同于WRAP_CONTENT。為什么會是這樣的結(jié)果呢?本人并沒有深究它的原因,但本人猜測(且后續(xù)并未去證實)這與mContentParent加載了布局后重新確定整個視圖的尺寸的過程脫不了干系。我們來翻翻ViewGroup的代碼,在ViewGroup中,有如下圖6所示的一段代碼。

【圖6】

對于一個ViewGroup及其子類來說,它的MeasureSpec要么是EXACTLY要么是AT_MOST,我記不清這里頭的具體關(guān)系了。但上圖6所示的代碼也已經(jīng)非常直白了。對于MATCH_PARENT,它確實是按照WRAP_CONTENT的方式來處理的。這也就解釋了上面所說的“令人費解”的情況了。雖然這個只是本人的猜測,但我估計也是差不多了。

而使用setContentView(View)的方式時,無論layout中根容器的寬高是什么,都按照WRAP_CONTENT的方式來走。這是為什么?我們先回去看看圖5所示代碼中這個方法的實現(xiàn)??梢园l(fā)現(xiàn),PhoneWindow給了一個默認的ViewGroup.LayoutParams對象。并且寬、高的值不偏不倚,正好是MATCH_PARENT。因此,當(dāng)使用這種方式時,無論layout中根容器的寬高如何設(shè)置,它都表現(xiàn)成按內(nèi)容的尺寸來適配布局的效果。因此,想要能控制對話框布局的尺寸,還是老老實實自己建一個有指定寬高值的LayoutParams對象給PhoneWindow對象吧

那么,到了這里,我們再來簡單探究一下,setContentView(int)又是如何做到可以直接設(shè)置尺寸的。我們回去圖3,看看這個方法的實現(xiàn)代碼中,第378行。它在映射xml時,第二個參數(shù)傳的直接是mContentParent。比較一下我們平時使用映射布局函數(shù)時,講道理,直接傳一個null的比較多吧,或者說,或許我們平時都很少注意到這個參數(shù)。我們?nèi)ayoutInflater中轉(zhuǎn)轉(zhuǎn)。

 import android.view.LayoutInflater;

inflate()方法的代碼還是挺長的,這里就不詳細貼了,我們只挑有代表性的來看。

public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)

// ...

final AttributeSet attrs = Xml.asAttributeSet(parser);

// ...

// Create layout params that match root, if supplied
params = root.generateLayoutParams(attrs);

// ...

// Temp is the root view that was found in the xml
final View temp = createViewFromTag(root, name, attrs, false);

// ...

if (root != null && attachToRoot) {
 root.addView(temp, params);
}
// ...

夠清晰了吧。在這里,LayoutInflater在映射xml布局時主動去解析了所有的屬性。當(dāng)然會包括外層容器的屬性。然后根據(jù)解析的結(jié)果生成一個LayoutParams對象,最后,再將要內(nèi)容布局聯(lián)合這個即時創(chuàng)建的LayoutParams對象一同添加到mContentParent容器中去,其實就相當(dāng)于調(diào)用setContentView(View, LayoutParams)方法。所以在文章開頭我才說到Dialog的三個設(shè)置內(nèi)容布局的方法本質(zhì)是一樣的,只是其封裝深度不同而已。

設(shè)置Dialog的背景為完全透明

Dialog默認有一個灰色的背景,首先這個背景巨丑,其次背景的存在還影響我們對對話框UI的定制。

   

在Activity中,可以通過在創(chuàng)建Dialog時傳入一個無背景對話框的風(fēng)格樣式給構(gòu)造器,以構(gòu)造出無灰色背景的對話框出來。也可以通過Java代碼控制對話框的背景色為透明色。還可以先show()對話框,然后再給它setContentView()來達到無背景色的對話框的目的。

1、 通過風(fēng)格樣式

 <style name="transBg" parent="@android:Theme.Dialog">
  <item name="android:windowBackground">@android:color/transparent"</item>
 </style> 

 AlertDialog dialog = new AlertDialog.Builder(mContext, R.style.transBg).create();
 //或
 Dialog dlg = new Dialog(mContext, R.style.transBg);
 //等 

2、通過Java代碼控制

所謂背景,其實就是PhoneWindow的背景。我們只需要設(shè)置PhoneWindow的背景為透明,就能達到我們想要的結(jié)果了。

// ...
AlertDialog dialog = builder.create();
dialog.show();
dialog.setContentView(view);
//方式1,使用透明的ColorDrawable對象。
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(0));
//方式2,使用一張透明的Drawable圖片。
dialog.getWindow().setBackgroundDrawableResource(R.drawable.transparent);

3、先顯示對話框再設(shè)置布局

這種方式只在Activity中有效果。

 AlertDialog dialog = builder.create();
 dialog.show();
 dialog.setContentView(view);

至于Service中為什么沒有效果,本人懷疑是由于在Service中要想彈出對話框,只能將它設(shè)為系統(tǒng)級對話框,需要加多的一段代碼導(dǎo)致的。但其具體原理還沒有去研究過。

dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

在Service中。只能通過上述第1、第2種方式來實現(xiàn)背景透明的目的。

以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時也希望多多支持腳本之家!

相關(guān)文章

  • Flutter之Timer實現(xiàn)短信驗證碼獲取60s倒計時功能的代碼

    Flutter之Timer實現(xiàn)短信驗證碼獲取60s倒計時功能的代碼

    這篇文章主要介紹了Flutter之Timer實現(xiàn)短信驗證碼獲取60s倒計時功能,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • Android Studio使用教程(四):Gradle基礎(chǔ)

    Android Studio使用教程(四):Gradle基礎(chǔ)

    這篇文章主要介紹了Android Studio使用教程(四):Gradle基礎(chǔ),本文講解了什么是Gradle、安裝Gradle、Gradle 基本概念等內(nèi)容,需要的朋友可以參考下
    2015-05-05
  • 安卓GreenDao框架一些進階用法整理

    安卓GreenDao框架一些進階用法整理

    本文主要對安卓GreenDao框架一些進階用法進行整理介紹,具有一定的參考價值,需要的朋友一起來看下吧
    2016-12-12
  • Android中通過view方式獲取當(dāng)前Activity的屏幕截圖實現(xiàn)方法

    Android中通過view方式獲取當(dāng)前Activity的屏幕截圖實現(xiàn)方法

    這篇文章主要介紹了Android中通過view方式獲取當(dāng)前Activity的屏幕截圖實現(xiàn)方法,本文方法相對簡單,容易理解,需要的朋友可以參考下
    2014-09-09
  • Kotlin中?和!!的區(qū)別詳細對比

    Kotlin中?和!!的區(qū)別詳細對比

    這篇文章主要給大家介紹了關(guān)于Kotlin中?和!!區(qū)別的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • 代碼實例分析android中inline hook

    代碼實例分析android中inline hook

    本片文章主要給大家通過代碼示例分析了android中inline hook的用法是實現(xiàn)過程,需要的朋友跟著參考下吧。
    2018-01-01
  • Android開發(fā)退出程序的方法匯總

    Android開發(fā)退出程序的方法匯總

    Android程序有很多Activity,比如說主窗口A,調(diào)用了子窗口B,子窗口B又調(diào)用子窗口C,back返回子窗口B后,在B中如何關(guān)閉整個Android應(yīng)用程序呢? 下面腳本之家小編就給大家介紹android開發(fā)退出程序的幾種方法,感興趣的朋友參考下吧
    2016-03-03
  • android APP登陸頁面適配的實現(xiàn)

    android APP登陸頁面適配的實現(xiàn)

    這篇文章主要介紹了android APP登陸頁面適配的實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-09-09
  • Android 實現(xiàn)電話來去自動錄音的功能

    Android 實現(xiàn)電話來去自動錄音的功能

    本文主要介紹Android 電話自動錄音功能的開發(fā),這里提供實現(xiàn)代碼和實現(xiàn)效果圖,有需要的小伙伴可以參考下
    2016-08-08
  • 基于Alarmmanager實現(xiàn)簡單鬧鐘功能

    基于Alarmmanager實現(xiàn)簡單鬧鐘功能

    這篇文章主要為大家詳細介紹了基于Alarmmanager實現(xiàn)簡單鬧鐘功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-06-06

最新評論

永安市| 句容市| 广饶县| 永兴县| 常山县| 白朗县| 拉萨市| 囊谦县| 固始县| 和田市| 林口县| 乐陵市| 高邑县| 长治市| 东港市| 连州市| 六枝特区| 海伦市| 慈溪市| 平和县| 八宿县| 易门县| 潮州市| 南昌县| 团风县| 凌海市| 奇台县| 玉林市| 万宁市| 滨州市| 托克逊县| 久治县| 山阳县| 郎溪县| 新平| 碌曲县| 股票| 武山县| 拉孜县| 昭平县| 和静县|