文章目录
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
CSDN:https://blog.csdn.net/confusing_awakening
OpenCV入门教程:https://blog.csdn.net/confusing_awakening/article/details/113372425
ffmpeg入门教程:https://blog.csdn.net/confusing_awakening/article/details/102007792
微信公众号
QQ群