Android屏幕適配之解決白屏啓動的正確姿勢

APP啓動頁的需求

做APP,往往要求在點擊桌面APP圖標啓動時,立馬顯示一個頁面,不能白屏、不能黑屏、不能拉伸、不能延遲。
在這裏插入圖片描述

APP啓動頁的需求的嘗試

有個方案是這樣的:用一張圖片做啓動頁背景圖,這樣當APP還沒有進入第一個Activity的頁面時,就能看到一個有圖文的頁面,而不至於白屏或者黑屏或者延遲。

定義正確的Theme

 <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    </style>
    <style name="StartTheme" parent="AppTheme">
        <item name="android:windowBackground">@drawable/background_splash</item>
        <item name="android:windowNoTitle">true</item>
    </style>

android:windowBackground屬性指定背景圖

定義背景圖

切得圖是1280x720的png圖片

background_splash:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/welcome" />
</layer-list>

運行到分辨率爲2160x1080的手機上明顯被拉伸,因爲用的圖是1280x720的png圖片,如果用1920x1080的手機測試是不會被拉伸的,因爲1920x1080和1280x720 剛好是寬高比例相等的

在這裏插入圖片描述
那是否可以直接用圖片指定屬性android:windowBackground呢?

<item name="android:windowBackground">@drawable/welcome</item>

明顯和上述方法一樣的結果,毫無疑問也是不行的。

是否可以用.9圖呢?

當然不行,因爲.9圖的目的是做文案或者控件的背景圖,並保證背景圖能容納下可變長度的文案或者控件,.9圖做啓動頁背景圖還是會被拉伸的。

小編強行試了下,什麼情況下可以用.9圖做啓動頁適配成功能呢?

用.9圖做啓動頁背景,你會發現沒設置拉伸的區域也被拉伸了,圖片會變形。可以通過調整拉伸區域的範圍做到適配。但這是不靠譜的,那麼多手機,你能給每一臺不同分辨率的手機調整一張.9圖,那意義何在?

解決白屏啓動的正確姿勢

既然不想圖片被拉伸,那我們可以將圖片居中啊,將圖片鋪在純色背景上

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/colorPrimary" />
    <item
        android:width="@dimen/dp360"
        android:height="@dimen/dp640"
        android:gravity="center"
        android:drawable="@drawable/welcome" />
</layer-list>

參考Andoid屏幕適配終極手段(小編用過最得勁的dp適配)https://www.jianshu.com/p/375d614401aa

運行到分辨率爲2160x1080並且寬度dp爲360的手機上,360dp*1280/720=640dp,高度dp設置爲640,發現1280x720的png圖片居中了,圖片沒有被拉伸

在這裏插入圖片描述
把背景色換成白色就相當奶思了
在這裏插入圖片描述

然而事情並沒有做完,寬高定爲360dp,只能適配寬度爲360dp的手機

    android:width="@dimen/dp360"
    android:height="@dimen/dp640"

如何適配儘可能多的寬度dp 手機呢?

參考Andoid屏幕適配終極手段(小編用過最得勁的dp適配)https://www.jianshu.com/p/375d614401aa

在java代碼目錄創建類DPGeneratorLittle ,修改工程目錄

root="F:\\AndroidStudioWorkSpace\\MyApplication2\\app\\src\\main\\res\\";

創建dimens文件,定義好需要用到的dp值

在這裏插入圖片描述
執行main方法


import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

public class DPGeneratorLittle {

    private static final String HEAD = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";//頭部
    private static final String START_TAG = "<resources>\n";//開始標籤
    private static final String END_TAG = "</resources>\n";//結束標籤


    private static final float DP_BASE = 360;//360dp爲基準

    private static final int DP_MAX = 720;//所有dimens文件dp從0生成到這個值
    private static final int SP_MAX = 48;//SP最大

    private static final int[] dps = {360, 384, 392, 400, 410, 411, 480, 533, 592,
            600, 640, 662, 720, 768, 800, 811, 820,900, 960, 961, 1024, 1280};//常見dp列表
//    private static final int[] dps = {100,481,510,720,900};//常見dp列表

    private static final String root="F:\\AndroidStudioWorkSpace\\MyApplication2\\app\\src\\main\\res\\";

    private static ExecutorService fixedThreadPool;//線程池,用於生成XML文件
    private static int size_thread = 5;//線程池大小


    private static DocumentBuilderFactory dbFactory;
    private static DocumentBuilder db;
    private static Document document;


    public static void main(String[] args) {
        try {
            dbFactory = DocumentBuilderFactory.newInstance();
            db = dbFactory.newDocumentBuilder();
            //將給定 URI 的內容解析爲一個 XML 文檔,並返回Document對象
            //記得改成自己當前項目的路徑
            document = db.parse(root+"values\\dimens.xml");


            //按文檔順序返回包含在文檔中且具有給定標記名稱的所有 Element 的 NodeList
            NodeList dimenList = document.getElementsByTagName("dimen");
            if (dimenList.getLength()==0)return;
            List<Dimen> list = new ArrayList<>();
            for (int i = 0; i < dimenList.getLength(); i++) {
                //獲取第i個book結點
                Node node = dimenList.item(i);
                //獲取第i個dimen的所有屬性
                NamedNodeMap namedNodeMap = node.getAttributes();
                //獲取已知名爲name的屬性值
                String atrName = namedNodeMap.getNamedItem("name").getTextContent();

                String value = node.getTextContent();

                System.out.println("+++atrName++++++++++++++++++++" + atrName);
                System.out.println("+++++++++++++value++++++++++" + value);


                list.add(new Dimen(atrName, value));


            }


            fixedThreadPool = Executors.newFixedThreadPool(size_thread);

            for (int i = 0; i < dps.length; i++) {

                XMLThread xmlThread = new XMLThread(i, list);
                fixedThreadPool.execute(xmlThread);//線程啓動執行

            }


        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();

        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        }


    }

    private static class XMLThread implements Runnable {

        private int index = 0;
        private List<Dimen> list;

        public XMLThread(int index, List<Dimen> list) {
            this.index = index;
            this.list = list;
        }

        @Override
        public void run() {
            //記得改成自己當前項目的路徑
            generateXMl(list, index, root+"values-sw" + dps[index] + "dp\\", "dimens.xml");
        }
    }


    private static void generateXMl(List<Dimen> list, int index, String pathDir, String fileName) {
        try {
            File diectoryFile = new File(pathDir);
            if (!diectoryFile.exists()) {
                diectoryFile.mkdirs();
            }
            File file = new File(pathDir + fileName);
            if (file.exists()) {
                file.delete();
            }
            FileWriter fileWriter = new FileWriter(file);
            fileWriter.write(HEAD);
            fileWriter.write(START_TAG);


            //?????????????????????????????????????????????
            int size = list.size();
            String atrName;
            String value;
            for (int i = 0; i < size; i++) {
                atrName = list.get(i).getAtrName();
                value = list.get(i).getValue();

                String output = "\t<dimen name=\"" + atrName + "\">" +
                        roundString(Float.valueOf(value.substring(0, value.length() - 2)), index) +
                        value.substring(value.length()-2)+"</dimen>\n";
                fileWriter.write(output);

            }

            fileWriter.write(END_TAG);
            fileWriter.flush();
            fileWriter.close();

            System.out.println("寫入成功");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("寫入失敗");


        }
    }

    //精確到小數點後2位,並且四捨五入(因爲有SW1280dp,基準是160dp,1dp=1px,
    // 如果精確到小數點後一位,四捨五入會有0.5dp誤差,在sw1280dp中會有4PX誤差,精確到小數點後2位,四捨五入,誤差控制在1PX之內)
    private static String roundString(float data, int index) {
        String result = "";
        float floatResult = data * dps[index] / DP_BASE;
        DecimalFormat df = new DecimalFormat("0.00");
        result = df.format(floatResult);
        return result;
    }

    private static class Dimen {
        private String atrName;
        private String value;

        public Dimen(String atrName, String value) {
            this.atrName = atrName;
            this.value = value;
        }

        public String getAtrName() {
            return atrName;
        }

        public void setAtrName(String atrName) {
            this.atrName = atrName;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }

}

你將收穫如下喜悅

在這裏插入圖片描述

GitHub:https://github.com/AnJiaoDe/White-screen-Solution

當然你也可以用PX適配的方式,

小編最喜歡的是如下的適配方式:

參考Andoid屏幕適配終極手段(小編用過最得勁的dp適配)https://www.jianshu.com/p/375d614401aa

歡迎分享、轉載、聯繫、指正、批評、撕逼

Github:https://github.com/AnJiaoDe

簡書:https://www.jianshu.com/u/b8159d455c69

CSDN:https://blog.csdn.net/confusing_awakening

ffmpeg入門教程:https://www.jianshu.com/p/042c7847bd8a

微信公衆號
這裏寫圖片描述

QQ羣

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章