主頁 > 移動端開發 > 聊聊獲取螢屏高度這件事

聊聊獲取螢屏高度這件事

2020-12-23 10:55:28 移動端開發

Navigation Deer

問題的起因是我發現 PopupWindow彈出位置不正確時發現的,其實早在兩年多前,我就發現我手上的小米MIX2s 獲取螢屏高度不正確,后面參考V2EX 的這篇帖子處理了,最近又一次做到類似功能,發現小米、vivo都出現了問題,所以有了今天的內容,

1.回顧過去

說起獲取螢屏高度,不知道你是如何理解這個高度范圍的?是以應用顯示區域高度作為螢屏高度還是手機螢屏的高度,

那么我們先看一下平時使用獲取高度的方法:

public static int getScreenHeight(Context context) {
	WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
	Display display = wm.getDefaultDisplay();
	DisplayMetrics dm = new DisplayMetrics();
	display.getMetrics(dm);
	return dm.heightPixels;
}

//或
public static int getScreenHeight(Context context) {
	WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
	Point point = new Point();
	wm.getDefaultDisplay().getSize(point);
	return point.y;
}

// 或
public static int getScreenHeight(Context context) {
	return context.getResources().getDisplayMetrics().heightPixels;
}
// 貌似還有更多的方法

以上三種效果一致,只是寫法略有不同,

當然你或許使用的是這種:

public static int getScreenHeight(Context context) {
	WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
	Display display = wm.getDefaultDisplay();
	DisplayMetrics dm = new DisplayMetrics();
	if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
		display.getRealMetrics(dm);
	} else {
		display.getMetrics(dm);
	}
	return dm.heightPixels;
}
// 其他幾種寫法大同小異
...

這個方法判斷了系統大于等于Android 4.2時,使用getRealMetricsgetRealSize)來獲取螢屏高度,那么這里發生了什么,為什么會這樣?

其實在Andoird 4.0時,引入了虛擬導航鍵,如果你繼續使用getMetrics之類的方式,獲取的高度是去除了導航欄的高度的,

當時因為在4.0和4.2之間還沒有的getRealMetrics這個方法,所以甚至需要添加下面的適配代碼:

try {
     heightPixels = (Integer) Display.class.getMethod("getRawHeight").invoke(display);
} catch (Exception e) {
}

現在不會還有人適配4.4甚至5.0一下的機子了吧,不會吧不會吧,,,所以歷史的包袱可以去掉了,

在這里插入圖片描述

上面方法名都是getScreenHeight,可是這個高度范圍到底和你需要的是否一致,這個需要開發時注意,我的習慣是ScreenHeight指應用顯示的高度,不包括導航欄(非全屏下),RealHeight來指包含導航欄和狀態欄的高度(getRealMetrics),

PS:以前也使用過AndroidUtilCode這個工具庫,里面將前者方法名定義為getAppScreenHeight,后者為getScreenHeight,也是很直觀的方法,

下文中我會以自己的習慣,使用ScreenHeightRealHeight來代表兩者,

我印象中華為手機很早就使用了虛擬導航鍵,如下圖(圖片來源):

華為手機
比較特別的是,當時華為的導航欄還可以顯示隱藏,注意圖中左下角的箭頭,點擊可以隱藏,上滑可以顯示,即使這樣,使用getScreenHeight也可以準確獲取高度,隱藏了ScreenHeight就等于RealHeight

上述的這一切在“全面屏”時代沒有到來之前,沒有什么問題,

2.立足當下

小米MIX的發布開啟了全面屏時代(16年底),以前的手機都是16:9的,記得雷布斯在發布會上說過,他們費了很大的力氣說服了谷歌去除了16:9的限制(從Android 7.0開始)
MIX 2發布會
MIX 2發布會

全面屏手機是真的香,不過隨之也帶來適配問題,首當其沖的就是劉海屏,各家有各自的獲取劉海區域大小的方法,主要原因還是國內競爭的激烈,各家為了搶占市場,先于谷歌定制了自己的方案,這一點讓人想起了萬惡的動態權限適配,,,

其實在劉海屏之下,還隱藏一個導航欄的顯示問題,也就是本篇的重點,全面屏追求更多的顯示區域,隨之帶來了手勢操作,在手勢操作模式下,導航欄是隱藏狀態,

本想著可以和上面提到的華為一樣,隱藏獲取的就是RealHeight,顯示就是減去導航欄高度的ScreenHeight,然而現實并不是這樣,下表是我收集的一些全面屏手機各高度的資料,

機型系統ScreenHeightRealHeightNavigationBarStatusBar是否有劉海
vivo Z3xFuntouch OS_10(Android 10)2201(2075)228012684
Xiaomi MIX 2sMIUI 12(Android 10)2030(2030)216013076
Redmi Note 8ProMIUI 11.0.3(Android 10)2134(2134)234013076
Redmi K30 5GMIUI 12.0.3(Android 10)2175(2175)240013095
Honor 10 LiteEMUI 10(Android 10)2259(2139)234012081
華為暢享 20EMUI 10.1.1(Android 10)1552(1472)16008048
OPPO Find XColorOS 7.1(Android 10)2340(2208)234013296
OnePlus 6H2OS 10.0.8(Android 10)2201(2159,2075)2280126(42)80

ScreenHeight一欄中括號內表示顯示導航欄時獲取的螢屏高度,

大致的規律總結如下:

  • 在有劉海的手機上,ScreenHeight不包含狀態欄高度,
  • 小米手機在隱藏顯示導航欄時,ScreenHeight不變,且不包含導航欄高度,

其中vivo手機,螢屏高度加狀態欄高度大于真實高度(2201 + 84 > 2280),本以為差值79是劉海高度,但查看vivo檔案后發現,vivo劉海固定27dp(81px),也還是對不上,,,

一加6最奇怪,三種設定模式,使用側邊全屏手勢時底部有一個小條,NavigationBar高度變為42,(2159 + 42 = 2075 + 126 = 2201)也就是說這種模式也屬于有導航欄的情況,

在這里插入圖片描述

這時如果你需要獲取準確的ScreenHeight,只有通過RealHeight - NavigationBar來實作了,

所以首先需要判斷當前導航欄是否顯示,再來決定是否減去NavigationBar高度,

先看看老牌的判斷方法如下:

public boolean isNavigationBarShow(){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        Display display = getWindowManager().getDefaultDisplay();
        Point size = new Point();
        Point realSize = new Point();
        display.getSize(size);
        display.getRealSize(realSize);
        return realSize.y!=size.y;
    } else {
        boolean menu = ViewConfiguration.get(this).hasPermanentMenuKey();
        boolean back = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
        if(menu || back) {
            return false;
        }else {
            return true;
        }
    }
}

此方法通過比較ScreenHeightRealHeight是否相等來判斷,如果對比上面表中的資料,那只有OPPO Find X可以判斷成功,也有一些方法通過ScreenHeightRealHeight差值來計算導航欄高度,顯然這些方法已無法再使用,

所以搜索了一下相關資訊,得到了下面的代碼:

	/**
     * 是否隱藏了導航鍵
     *
     * @param context
     * @return
     */
    public static boolean isNavBarHide(Context context) {
        try {
            String brand = Build.BRAND;
            // 這里做判斷主要是不同的廠商注冊的表不一樣
            if (!StringUtils.isNullData(brand) && (Rom.isVivo() || Rom.isOppo())) {
                return Settings.Secure.getInt(context.getContentResolver(), getDeviceForceName(), 0) != 0;
            } else if (!StringUtils.isNullData(brand) && Rom.isNokia()) {
                //甚至 nokia 不同版本注冊的表不一樣, key 還不一樣,,,
                return Settings.Secure.getInt(context.getContentResolver(), "swipe_up_to_switch_apps_enabled", 0) == 1
                        || Settings.System.getInt(context.getContentResolver(), "navigation_bar_can_hiden", 0) != 0;
            } else
                return Settings.Global.getInt(context.getContentResolver(), getDeviceForceName(), 0) != 0;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
 
    /**
     * 各個手機廠商注冊導航鍵相關的 key
     *
     * @return
     */
    public static String getDeviceForceName() {
        String brand = Build.BRAND;
        if (StringUtils.isNullData(brand))
            return "navigationbar_is_min";
        if (brand.equalsIgnoreCase("HUAWEI") || "HONOR".equals(brand)) {
            return "navigationbar_is_min";
        } else if (Rom.isMiui()||Rom.check("XIAOMI")) {
            return "force_fsg_nav_bar";
        } else if (Rom.isVivo()) {
            return "navigation_gesture_on";
        } else if (Rom.isOppo()) {
            return "hide_navigationbar_enable";
        } else if (Rom.check("samsung")) {
            return "navigationbar_hide_bar_enabled";
        } else if (brand.equalsIgnoreCase("Nokia")) {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
                return "navigation_bar_can_hiden";
            } else {
                return "swipe_up_to_switch_apps_enabled";
            }
        } else {
            return "navigationbar_is_min";
        }
    }

可以看到包含了華為、小米、vivo、oppo 、三星甚至諾基亞的判斷,這就是適配的現實狀況,不要妄想尋找什么通用方法,老老實實一個個判斷吧,畢竟幺蛾子就是這些廠家搞出來的,廠家魔改教你做人,

這種方法在上面的測驗機中都親測準確有效,

不過這個判斷方法不夠嚴謹,比如其他品牌手機使用此方法,那么結果都是false,用這樣的結果來計算高度顯得不夠嚴謹,

根據前面提到問題發生的原因是全面屏帶來的(7.0及以上),所以我們可以先判斷是否是全面屏手機(螢屏長寬比例超過1.86以上),然后判斷是否顯示導航欄,對于不確定的機型,我們還是使用原先的ScreenHeight,盡量控制影響范圍,

我整理的代碼如下(補充了錘子手機判斷):

/**
 * @author weilu
 **/
public class ScreenUtils {

	private static final String BRAND = Build.BRAND.toLowerCase();

	public static boolean isXiaomi() {
		return Build.MANUFACTURER.toLowerCase().equals("xiaomi");
	}

	public static boolean isVivo() {
		return BRAND.contains("vivo");
	}

	public static boolean isOppo() {
		return BRAND.contains("oppo") || BRAND.contains("realme");
	}

	public static boolean isHuawei() {
		return BRAND.contains("huawei") || BRAND.contains("honor");
	}

	public static boolean isOneplus(){
		return BRAND.contains("oneplus");
	}
	
	public static boolean isSamsung(){
		return BRAND.contains("samsung");
	}
	
	public static boolean isSmartisan(){
		return BRAND.contains("smartisan");
	}

	public static boolean isNokia() {
		return BRAND.contains("nokia");
	}
	
	public static boolean isGoogle(){
		return BRAND.contains("google");
	}


	public static int getRealScreenHeight(Context context) {
		WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
		Display display = wm.getDefaultDisplay();
		DisplayMetrics dm = new DisplayMetrics();
		display.getRealMetrics(dm);
		return dm.heightPixels;
	}
	
	public static int getRealScreenWidth(Context context) {
		WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
		Display display = wm.getDefaultDisplay();
		DisplayMetrics dm = new DisplayMetrics();
		display.getRealMetrics(dm);
		return dm.widthPixels;
	}

	public static int getScreenHeight(Context context) {
		WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
		Display display = wm.getDefaultDisplay();
		DisplayMetrics dm = new DisplayMetrics();
		display.getMetrics(dm);
		return dm.heightPixels;
	}


	/**
	 * 判斷設備是否顯示NavigationBar
	 *
	 * @return 其他值 不顯示 0顯示 -1 未知
	 */
	public static int isNavBarHide(Context context) {
		// 有虛擬鍵,判斷是否顯示
		if (isVivo()) {
			return vivoNavigationEnabled(context);
		}
		if (isOppo()) {
			return oppoNavigationEnabled(context);
		}
		if (isXiaomi()) {
			return xiaomiNavigationEnabled(context);
		}
		if (isHuawei()) {
			return huaWeiNavigationEnabled(context);
		}
		if (isOneplus()) {
			return oneplusNavigationEnabled(context);
		}
		if (isSamsung()) {
			return samsungNavigationEnabled(context);
		}
		if (isSmartisan()) {
			return smartisanNavigationEnabled(context);
		}
		if (isNokia()) {
			return nokiaNavigationEnabled(context);
		}
		if (isGoogle()) {
			// navigation_mode 三種模式均有導航欄,只是高度不同,
			return 0;
		}
		return 2;
	}

	/**
	 * 判斷當前系統是使用導航鍵還是手勢導航操作
	 *
	 * @param context
	 * @return 0 表示使用的是虛擬導航鍵,1 表示使用的是手勢導航,默認是0
	 */
	public static int vivoNavigationEnabled(Context context) {
		return Settings.Secure.getInt(context.getContentResolver(), "navigation_gesture_on", 0);
	}

	public static int oppoNavigationEnabled(Context context) {
		return Settings.Secure.getInt(context.getContentResolver(), "hide_navigationbar_enable", 0);
	}

	public static int xiaomiNavigationEnabled(Context context) {
		return Settings.Global.getInt(context.getContentResolver(), "force_fsg_nav_bar", 0);
	}

	private static int huaWeiNavigationEnabled(Context context) {
		return Settings.Global.getInt(context.getContentResolver(), "navigationbar_is_min", 0);
	}

	/**
	 * @param context
	 * @return 0虛擬導航鍵  2為手勢導航
	 */
	private static int oneplusNavigationEnabled(Context context) {
		int result = Settings.Secure.getInt(context.getContentResolver(), "navigation_mode", 0);
		if (result == 2) {
			// 兩種手勢 0有按鈕, 1沒有按鈕
			if (Settings.System.getInt(context.getContentResolver(), "buttons_show_on_screen_navkeys", 0) != 0) {
				return 0;
			}
		}
		return result;
	}

	public static int samsungNavigationEnabled(Context context) {
		return Settings.Global.getInt(context.getContentResolver(), "navigationbar_hide_bar_enabled", 0);
	}

	public static int smartisanNavigationEnabled(Context context) {
		return Settings.Global.getInt(context.getContentResolver(), "navigationbar_trigger_mode", 0);
	}

	public static int nokiaNavigationEnabled(Context context) {
		boolean result = Settings.Secure.getInt(context.getContentResolver(), "swipe_up_to_switch_apps_enabled", 0) != 0
				|| Settings.System.getInt(context.getContentResolver(), "navigation_bar_can_hiden", 0) != 0;

		if (result) {
			return 1;
		} else {
			return 0;
		}
	}


	public static int getNavigationBarHeight(Context context){
		int resourceId = context.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
		if (resourceId > 0) {
			return context.getResources().getDimensionPixelSize(resourceId);
		}
		return 0;
	}

	private static boolean isAllScreenDevice(Context context) {
		if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
			// 7.0放開限制,7.0以下都不為全面屏
			return false;
		} else {
			int realWidth = getRealScreenWidth(context);
			int realHeight = getRealScreenHeight(context);

			float width;
			float height;
			if (realWidth < realHeight) {
				width = realWidth;
				height = realHeight;
			} else {
				width = realHeight;
				height = realWidth;
			}
			// Android中默認的最大螢屏縱橫比為1.86
			return height / width >= 1.86f;
		}
	}

	/**
	 * 獲取去除導航欄高度的剩余高度(含狀態欄)
	 * @param context
	 * @return
	 */
	public static int getScreenContentHeight(Context context) {

		if (isAllScreenDevice(context)) {

			int result = isNavBarHide(context);

			int result = isNavBarHide(context);

			if (result == 0) {
				return getRealScreenHeight(context) - getNavigationBarHeight(context);
			} else if (result == -1){
				// 未知
				return getScreenHeight(context);
			} else {
				return getRealScreenHeight(context);
			}
		} else {
			return getScreenHeight(context);
		}

	}
}

有人會問,這些key都是哪里來的?畢竟我在廠商檔案也沒有翻到,

我能想到的辦法是查看SettingsProvider,它是提供設定資料的Provider,分有GlobalSystemSecure三種型別,上面代碼中可以看到不同品牌存放在的型別都不同,我們可以通過adb命令查看所有資料,根據navigation等關鍵字去尋找,比如查看Secure的資料:

	adb shell settings list secure

或者:

	ContentResolver cr = context.getContentResolver();
	Uri uri = Uri.parse("content://settings/secure/");
	Cursor cursor = cr.query(uri, null, null, null, null);
	while (cursor.moveToNext()) {
		String name = cursor.getString(cursor.getColumnIndex("name"));
		String value = cursor.getString(cursor.getColumnIndex("value"));
		Log.d("settings:", name + "=" + value);
	}
	cursor.close();		

這樣如果有上面兼容不到的機型,可以使用這個方法適配,也歡迎你的補充反饋,

費了這么大的勁獲取到了準確的高度,可能你會說,還不如直接獲取ContentView的高度:

	public static int getContentViewHeight(Activity activity) {
		View contentView = activity.getWindow().getDecorView().findViewById(android.R.id.content);
		return contentView.getHeight();
	}

這個結果和上述計算的高度一致,唯一的限制是需要在onWindowFocusChanged之后呼叫,否則高度為0,這個我們可以根據實際情況自行選用,

3.已知問題

  • 網上有許多同類代碼,發現會將vivo和oppo都使用navigation_gesture_on這一個key,我在oppo Find x中發現此key并不存在,不知是否和系統版本有關,如果是的話,又需要判斷oppo的系統版本了,

  • 上面提到的獲取導航欄高度的方法在部分手機中無效,無效的原因是因為導航欄隱藏時,獲取高度就為0,所以判斷是否顯示導航欄是關鍵,

  • 劉海的出現,很多人會吐槽丑,所以廠家想到了隱藏劉海的方式(掩耳盜鈴),比如下面是Redmi K30的設定頁面:

設定劉海顯示頁

第二種沒啥特別,就是狀態欄強制為黑色,這里我懷疑因為這個設定,導致在有劉海的手機上,ScreenHeight不包含狀態欄高度,

最糟糕的是第三種,隱藏后狀態欄在劉海外,例如Redmi K30在開啟后,ScreenHeight 為2174,RealHeight為2304,而關閉時為2175 和 2400,這下連萬年不變的RealHeight也變化了,這太不real了,大家自行體會,不過目前發現未影響適配方案,不知其他手機如何,

對于是否隱藏劉海,其實也是有各家的判斷的,比如小米:

	// 0:顯示劉海,1:隱藏劉海
	Settings.Global.getInt(context.getContentResolver(), "force_black", 0);
  • 有些App會使用修改density的螢屏適配方案,這會影響獲取導航欄高度的方法,比如130px的導航欄適配后獲取到的是136px,所以這里需要使用getSystem中的density轉換回去:
	public static int getNavigationBarHeight(Context context){
		int resourceId = context.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
		if (resourceId > 0) {
			int height = context.getResources().getDimensionPixelSize(resourceId);
			// 兼容螢屏適配導致density修改
			float density = context.getResources().getDisplayMetrics().density;
			if (DENSITY != density) {
				return dpToPx(px2dp(context, height));
			}
			return height;
		}
		return 0;
	}

	public static final float DENSITY = Resources.getSystem().getDisplayMetrics().density;

	public static int dpToPx(int dpValue) {
		return (int) (dpValue * DENSITY + 0.5f);
	}

	public static int px2dp(Context context, int px) {
		return (int) (px / context.getResources().getDisplayMetrics().density + 0.5);
	}

getSystem原始碼如下:

	/**
     * Return a global shared Resources object that provides access to only
     * system resources (no application resources), is not configured for the
     * current screen (can not use dimension units, does not change based on
     * orientation, etc), and is not affected by Runtime Resource Overlay.
     */
    public static Resources getSystem() {
        synchronized (sSync) {
            Resources ret = mSystem;
            if (ret == null) {
                ret = new Resources();
                mSystem = ret;
            }
            return ret;
        }
    }

它不受資源覆寫的影響,我們可以通過它將值轉換回來,

4.展望未來

本篇看似聊的獲取高度這件事,其實伴隨導航欄的發展演進,核心是是如何判斷導航欄是否顯示,

通過上面的介紹,總結一下就是在“全面屏時代”,如果你想獲取螢屏高度,就不要使用ScreenHeight了,否則會出現UI展示上的問題,而且這種問題,線上也不會崩潰,難以發現,以前在支付寶中就發現過 PopupWindow彈出高度不正確的問題,過了好久才修復了,

至于螢屏寬度,也不清楚隨著折疊屏、環繞屏的到來會不會造成影響,但愿不要吧,碎片化原來越嚴重了,,,

最后,如果本文對你有啟發有幫助,點個贊和收藏可好?

參考

  • Android 獲取螢屏高度,虛擬導航鍵檢測

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/239084.html

標籤:其他

上一篇:Zabbix部署

下一篇:支付寶小程式下載圖片到服務器

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more