解決Popwindow寬高的問題。

問題

在使用Popwindow進行自定義的過程中,需要設置popwindow的寬高。但是寬高很多時候容易出問題。比如下面的例子。

布局文件如下

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#77000000"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:background="#fff"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="44dp"android:layout_margin="12dp"android:background="@drawable/cz_add_rzh_bg"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:drawableStart="@drawable/cz_icon_add_rzh"android:drawablePadding="4dp"android:text="申請注冊入駐號"android:textColor="#ff333333"android:textSize="14sp" /></RelativeLayout></LinearLayout><Viewandroid:id="@+id/close_layout"android:layout_width="match_parent"android:layout_height="100dp"/>
</LinearLayout>

使用了傳統方法設置寬高
在這里插入圖片描述
實際顯示效果很差,沒有內容只有一個黑色透明背景。
在這里插入圖片描述

解決方案

為了解決這個問題,我寫了個工具類。原理就是內部創建一個鋪面全屏的FrameLayout。在填充布局的時候作為父布局,來自動計算寬高。在通過其內部的LayoutParam來獲取寬高,如果寬高是-1的話,(MATCH_PARENT的值)就替換成屏幕的寬高。在編程實踐中Popwindow一般會顯示在某個控件的下面,這個時候布局中的高度match_parent對應的就不是手機屏幕的高度,而是需要減去上方空間占用的高度。這個時候就可以傳入上方控件,可以自動計算被使用的高度。

優化

加入了頂部view的處理

package com.trs.nmip.common.util.web;import android.content.Context;
import android.util.DisplayMetrics;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;import androidx.annotation.LayoutRes;/*** @author: zhuguohui* @date: 2025/3/21* @description: 用于獲取View大小的工具類*/
public class ViewSizeUtil {private static FrameLayout fullScreenView;private static FrameLayout getFullScreenView(Context ctx) {if (fullScreenView == null) {fullScreenView = new FrameLayout(ctx);fullScreenView.measure(getWidthMeasureSpec(ctx), getHeightMeasureSpec(ctx));fullScreenView.layout(0, 0, getScreenWidth(ctx), getScreenHeight(ctx));}return fullScreenView;}public static class Size {public  int width;public  int height;public Size(int width, int height) {this.width = width;this.height = height;}}/*** 填充布局,獲取寬高,用于在沒有父view的情況下,計算寬高** @param ctx      上下文* @param layoutId 布局id* @param topView  在其上面的控件,比如popWindow,如果要顯示在某個控件下面,并且當前控件的高度需要鋪面全屏的話。*                 那么就會減去topView所占用的高度。* @return 一個pair對象,第一個元素是view,第二個是寬高*/public static Pair<View, Size> inflateViewAndGetSize(Context ctx, @LayoutRes int layoutId, View topView, int yOffset) {View view = LayoutInflater.from(ctx).inflate(layoutId, getFullScreenView(ctx), false);ViewGroup.LayoutParams layoutParams = view.getLayoutParams();int width = layoutParams.width;int height = layoutParams.height;if (width == -1) {width = getScreenWidth(ctx);}if (height == -1) {height = getScreenHeight(ctx);//如果是鋪滿全屏,還要顯示在某個控件下面,需要減去這個控件使用的距離if (topView != null) {int[] location = new int[2];topView.getLocationOnScreen(location);int useHeight = location[1] + topView.getHeight();height -= useHeight;}}height += yOffset;return new Pair<>(view, new Size(width, height));}private static int getScreenWidth(Context context) {WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);DisplayMetrics dm = new DisplayMetrics();wm.getDefaultDisplay().getMetrics(dm);return dm.widthPixels;}private static int getScreenHeight(Context context) {DisplayMetrics displayMetrics = new DisplayMetrics();((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRealMetrics(displayMetrics);int screenHeight = displayMetrics.heightPixels;return screenHeight;}private static int getWidthMeasureSpec(Context ctx) {return View.MeasureSpec.makeMeasureSpec(getScreenWidth(ctx), View.MeasureSpec.AT_MOST);}private static int getHeightMeasureSpec(Context ctx) {return View.MeasureSpec.makeMeasureSpec(getScreenHeight(ctx), View.MeasureSpec.AT_MOST);}}

使用方法如下。

public class ChangeRzhPopWindow extends PopupWindow {public ChangeRzhPopWindow(Context context,View topView) {super(context);Pair<View, ViewSizeUtil.Size> pair = ViewSizeUtil.inflateViewAndGetSize(context, R.layout.change_rzh_pop_window,topView);setContentView(pair.first);setWidth(pair.second.width);setHeight(pair.second.height);setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));setFocusable(true);setOutsideTouchable(true);//因為背景是我們創建的。所以需要我們實現點擊背景關閉的功能pair.first.findViewById(R.id.close_layout).setOnClickListener(v-> dismiss());}
}

效果如下

紅色的地方就是頂部view

在這里插入圖片描述

遇到的問題

在開發中遇到一個通過代碼獲取的屏幕高度和手機時間高度不一致的情況,通過AI查詢得到這樣的結果。測試沒問題。特此記錄一下。

在這里插入圖片描述

提取基類

把上面的功能提取一個基類。這樣可以方便處理這些問題。這個基類還實現了LifecycleOwner 。更方便使用。

package com.trs.app.gzcz.content_manage.ui.rzh_title_bar.change_rzh_pop_window;import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.util.Pair;
import android.view.View;
import android.widget.PopupWindow;import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LifecycleRegistry;import com.trs.news.R;
import com.trs.nmip.common.util.web.ViewSizeUtil;/**** @author: zhuguohui* @date: 2025/3/21* @description: 自動處理寬高的PopupWindow* 加入了LifeCycleOwner的功能*/
public class EasySizePopupWindow extends PopupWindow implements LifecycleOwner {LifecycleRegistry registry=new LifecycleRegistry(this);{registry.setCurrentState(Lifecycle.State.INITIALIZED);}protected void setContentView(Context context, @LayoutRes  int layoutId, View topView,int yOffset){Pair<View, ViewSizeUtil.Size> pair = ViewSizeUtil.inflateViewAndGetSize(context, layoutId,topView,yOffset);setContentView(pair.first);setWidth(pair.second.width);setHeight(pair.second.height);setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));setFocusable(true);setOutsideTouchable(true);//因為背景是我們創建的。所以需要我們實現點擊背景關閉的功能pair.first.findViewById(R.id.close_layout).setOnClickListener(v-> dismiss());}@Overridepublic void showAsDropDown(View anchor) {super.showAsDropDown(anchor);}@Overridepublic void showAsDropDown(View anchor, int xoff, int yoff) {super.showAsDropDown(anchor, xoff, yoff);}@Overridepublic void showAsDropDown(View anchor, int xoff, int yoff, int gravity) {super.showAsDropDown(anchor, xoff, yoff, gravity);updateLifecycleState();}@Overridepublic void showAtLocation(View parent, int gravity, int x, int y) {super.showAtLocation(parent, gravity, x, y);updateLifecycleState();}@Overridepublic void dismiss() {super.dismiss();updateLifecycleStateToDismiss();}private void updateLifecycleStateToDismiss(){registry.setCurrentState( Lifecycle.State.CREATED);registry.setCurrentState( Lifecycle.State.STARTED);registry.setCurrentState( Lifecycle.State.DESTROYED);}private void updateLifecycleState(){registry.setCurrentState( Lifecycle.State.CREATED);registry.setCurrentState( Lifecycle.State.STARTED);registry.setCurrentState( Lifecycle.State.RESUMED);}@NonNull@Overridepublic Lifecycle getLifecycle() {return registry;}
}

使用

public class ChangeRzhPopWindow extends EasySizePopupWindow {public ChangeRzhPopWindow(Context context, View topView) {super();setContentView(context, R.layout.change_rzh_pop_window, topView);//因為背景是我們創建的。所以需要我們實現點擊背景關閉的功能getContentView().findViewById(R.id.close_layout).setOnClickListener(v-> dismiss());}}

關于全屏高度問題

如果當前頁面的布局是沉浸式的。那么使用PopupWindowshowAsDropDown會出現位置不對的情況。需要加上偏移量。
就可以完美顯示了。
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/73037.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/73037.shtml
英文地址,請注明出處:http://en.pswp.cn/web/73037.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MySQL數據庫精研之旅第二期:庫操作的深度探索

專欄&#xff1a;MySQL數據庫成長記 個人主頁&#xff1a;手握風云 目錄 一、查看數據庫 二、創建數據庫 2.1. 語法 2.2. 示例 三、字符集編碼和校驗(排序)規則 3.1. 查看數據庫支持的字符集編碼 3.2. 查看數據庫支持的排序規則 3.3. 不同的字串集與排序規則對數據庫的…

基于deepseek的智能語音客服【第四講】封裝milvus數據庫連接池封裝

通過工廠模式創建鏈接 static {// 創建連接池工廠BasePooledObjectFactory<MilvusServiceClient> factory new BasePooledObjectFactory<MilvusServiceClient>() {Overridepublic MilvusServiceClient create() throws Exception {return new MilvusServiceClient…

STM32基礎教程——定時器

前言 TIM定時器&#xff08;Timer&#xff09;:STM32的TIM定時器是一種功能強大的外設模塊&#xff0c;通過時基單元&#xff08;包含預分頻器、計數器和自動重載寄存器&#xff09;實現精準定時和計數功能。其核心原理是&#xff1a;內部時鐘&#xff08;CK_INT&#xff09;或…

OpenCV旋轉估計(4)生成一個字符串表示的匹配圖函數 matchesGraphAsString()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 matchesGraphAsString 函數是OpenCV庫中的一部分&#xff0c;位于 cv::detail 命名空間下。這個函數的主要作用是生成一個字符串表示的匹配圖&am…

Android 根據Url使用Retrofit框架進行文件下載

一、背景 根據后端返回的url下載地址,去執行文件下載&#xff0c;將文件保存到SD卡。這里使用Retrofit網絡框架。 二、代碼實現 2.1、定義一個DownloadFileService interface DownloadFileService {StreamingGETsuspend fun downloadFile(Url fileUrl: String):ResponseBody…

NVMe(Non-Volatile Memory Express)詳解

一、NVMe的定義與核心特性 NVMe&#xff08;非易失性內存主機控制器接口規范&#xff09;是一種 基于PCIe總線的高性能存儲協議&#xff0c;專為固態硬盤&#xff08;SSD&#xff09;設計&#xff0c;旨在替代傳統的AHCI協議&#xff08;如SATA&#xff09;。其核心特性包括&a…

機器學習——KNN超參數

sklearn.model_selection.GridSearchCV 是 scikit-learn 中用于超參數調優的核心工具&#xff0c;通過結合交叉驗證和網格搜索實現模型參數的自動化優化。以下是詳細介紹&#xff1a; 一、功能概述 GridSearchCV 在指定參數網格上窮舉所有可能的超參數組合&#xff0c;通過交叉…

穩定運行的以Oracle NoSQL數據庫為數據源和目標的ETL性能變差時提高性能方法和步驟

提高基于Oracle NoSQL數據庫的ETL&#xff08;提取、轉換、加載&#xff09;性能時&#xff0c;主要從多個角度進行優化。 提高基于Oracle NoSQL數據庫的ETL性能需要綜合考慮多個方面&#xff0c;關鍵是減少不必要的I/O操作、優化數據轉換和加載過程、合理配置Oracle NoSQL數據…

Compose 原理解析

Compose 的組件都是放在 setContent() 之后才能顯示的&#xff0c;那需要先看看這個函數的作用。 先看 ComponentActivity 的擴展函數 setContent()&#xff1a; /*** 將給定的可組合項合成到給定的 Activity 中。[content] 將成為給定 Activity 的根視圖。* 這大致相當于使用…

細說衛星導航:測距定位原理

測距定位原理 1. 偽距測量技術 核心原理&#xff1a;衛星發射信號&#xff0c;用戶接收并記錄傳播時間&#xff0c;乘以光速得到距離&#xff08;偽距&#xff09;。 技術細節&#xff1a; 信號傳播路徑分析 信號結構&#xff1a; 衛星信號包含三部分&#xff1a; 載波&…

19921 多重背包

19921 多重背包 ??難度&#xff1a;中等 &#x1f31f;考點&#xff1a;動態規劃、背包問題 &#x1f4d6; &#x1f4da; import java.util.Arrays; import java.util.LinkedList; import java.util.Queue; import java.util.Scanner;public class Main {static int N …

js逆向之斷點調試

1.XHR/提取斷點用法 當刷新頁面時候&#xff0c;有大量請求&#xff0c;并且你無法定位參數信息的時候&#xff0c;或者參數被混淆無法搜到&#xff0c;可以用該方法&#xff0c;該方法是會捕獲所有請求連接&#xff0c;然后我們通過連接過濾出自己想要的請求&#xff0c;然后…

基于32單片機的無人機直流電機閉環調速系統設計

標題:基于32單片機的無人機直流電機閉環調速系統設計 內容:1.摘要 本文針對無人機直流電機調速需求&#xff0c;設計了基于32單片機的無人機直流電機閉環調速系統。背景在于無人機應用場景不斷拓展&#xff0c;對電機調速精度和穩定性要求日益提高。目的是開發一套高精度、響應…

如何用Deepseek制作流程圖?

使用Deepseek制作流程圖&#xff0c;本質上是讓AI根據你的需求&#xff0c;生成相關流程圖的代碼&#xff0c;然后在流程圖編輯器中渲染&#xff0c;類似于Python一樣&#xff0c;ChatGPT可以生成代碼&#xff0c;但仍需在IDE中執行。 你知道繪制流程圖最高效的工具是什么嗎&a…

嵌入式硬件工程師從小白到入門-原理圖(三)

原理圖繪制從小白到入門&#xff1a;知識點速通與注意事項 一、原理圖繪制基礎概念 什么是原理圖&#xff1f; 原理圖&#xff08;Schematic&#xff09;是電子電路的圖形化表示&#xff0c;展示元器件之間的電氣連接關系&#xff0c;是硬件設計的藍圖。 核心元素 元器件符號&…

WSL 環境橋接與雷達通信配置筆記

作者: DWDROME 維護時間: 2025-03-22 參考文章:Windows子系統&#xff08;WSL&#xff09;通過橋接網絡實現被外部局域網主機直接訪問 WSL 環境橋接與雷達通信配置筆記 環境說明 Windows 11 專業版&#xff08;啟用 Hyper-V&#xff09;WSL2 Ubuntu 20.04物理網線&#xff08…

ToDesk云電腦各類鼠標有什么區別?虛擬/3D/游戲鼠標等各有利

不知道各位在使用ToDesk云電腦的時候是否是有注意到&#xff0c;這其中的鼠標竟有多種名稱、多種模式可以選&#xff0c;比如鎖定鼠標、3D鼠標、游戲鼠標這幾項。 那么這些不同名稱的鼠標都代表什么意思吶&#xff0c;又應該怎么選擇、怎么用吶&#xff1f;本篇內容小編就為大…

DeepBI:重構流量邏輯,助力亞馬遜廣告實現高效流量增長

在日益激烈的跨境電商競爭環境中&#xff0c;廣告投放早已從“粗放撒網”走向“精細化運營”。尤其是在亞馬遜這樣一個成熟且競爭白熱化的平臺&#xff0c;如何在廣告預算有限的前提下實現高效曝光、精準觸達、穩定轉化&#xff0c;成為眾多賣家和運營團隊面臨的核心挑戰。 De…

java項目之基于ssm的畢業論文管理系統(源碼+文檔)

項目簡介 畢業論文管理系統實現了以下功能&#xff1a; 本畢業論文管理系統主要實現的功能模塊包括學生模塊、導師模塊和管理員模塊三大部分&#xff0c;具體功能分析如下&#xff1a; &#xff08;1&#xff09;導師功能模塊&#xff1a;導師注冊登錄后主要功能模塊包括個人…

【自學筆記】Linux基礎知識點總覽-持續更新

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 Linux 基礎知識點總覽目錄Linux 簡介文件和目錄結構常用命令文件操作目錄操作權限管理文本處理 Shell 腳本基礎進程管理用戶和組管理網絡配置 總結 Linux 基礎知識點…