Repository: JessYanCoding/AndroidAutoSize Branch: master Commit: e402ecdd998e Files: 106 Total size: 258.1 KB Directory structure: gitextract_fstq_3r4/ ├── .github/ │ └── ISSUE_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README-zh.md ├── README.md ├── _config.yml ├── autosize/ │ ├── .gitignore │ ├── bintray.gradle │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ └── java/ │ └── me/ │ └── jessyan/ │ └── autosize/ │ ├── ActivityLifecycleCallbacksImpl.java │ ├── AutoAdaptStrategy.java │ ├── AutoSize.java │ ├── AutoSizeCompat.java │ ├── AutoSizeConfig.java │ ├── DefaultAutoAdaptStrategy.java │ ├── DisplayMetricsInfo.java │ ├── FragmentLifecycleCallbacksImpl.java │ ├── FragmentLifecycleCallbacksImplToAndroidx.java │ ├── InitProvider.java │ ├── WrapperAutoAdaptStrategy.java │ ├── external/ │ │ ├── ExternalAdaptInfo.java │ │ └── ExternalAdaptManager.java │ ├── internal/ │ │ ├── CancelAdapt.java │ │ └── CustomAdapt.java │ ├── onAdaptListener.java │ ├── unit/ │ │ ├── Subunits.java │ │ └── UnitsManager.java │ └── utils/ │ ├── AutoSizeLog.java │ ├── AutoSizeUtils.java │ ├── Preconditions.java │ └── ScreenUtils.java ├── build.gradle ├── demo/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ ├── androidTest/ │ │ └── java/ │ │ └── me/ │ │ └── jessyan/ │ │ └── autosize/ │ │ └── demo/ │ │ └── ExampleInstrumentedTest.java │ ├── main/ │ │ ├── AndroidManifest.xml │ │ ├── java/ │ │ │ └── me/ │ │ │ └── jessyan/ │ │ │ └── autosize/ │ │ │ └── demo/ │ │ │ ├── BaseApplication.java │ │ │ ├── CustomAdaptActivity.java │ │ │ ├── CustomFragment1.java │ │ │ ├── CustomFragment2.java │ │ │ ├── CustomFragment3.java │ │ │ ├── FragmentHost.java │ │ │ └── MainActivity.java │ │ └── res/ │ │ ├── drawable/ │ │ │ └── ic_launcher_background.xml │ │ ├── drawable-v24/ │ │ │ └── ic_launcher_foreground.xml │ │ ├── layout/ │ │ │ ├── activity_custom_adapt.xml │ │ │ ├── activity_host.xml │ │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26/ │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ └── values/ │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test/ │ └── java/ │ └── me/ │ └── jessyan/ │ └── autosize/ │ └── demo/ │ └── ExampleUnitTest.java ├── demo-androidx/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ ├── androidTest/ │ │ └── java/ │ │ └── me/ │ │ └── jessyan/ │ │ └── autosize/ │ │ └── demo/ │ │ └── ExampleInstrumentedTest.java │ ├── main/ │ │ ├── AndroidManifest.xml │ │ ├── java/ │ │ │ └── me/ │ │ │ └── jessyan/ │ │ │ └── autosize/ │ │ │ └── demo/ │ │ │ └── androidx/ │ │ │ ├── BaseApplication.java │ │ │ ├── CustomAdaptActivity.java │ │ │ ├── CustomFragment1.java │ │ │ ├── CustomFragment2.java │ │ │ ├── CustomFragment3.java │ │ │ ├── FragmentHost.java │ │ │ └── MainActivity.java │ │ └── res/ │ │ ├── drawable/ │ │ │ └── ic_launcher_background.xml │ │ ├── drawable-v24/ │ │ │ └── ic_launcher_foreground.xml │ │ ├── layout/ │ │ │ ├── activity_custom_adapt.xml │ │ │ ├── activity_host.xml │ │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26/ │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ └── values/ │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test/ │ └── java/ │ └── me/ │ └── jessyan/ │ └── autosize/ │ └── demo/ │ └── ExampleUnitTest.java ├── demo-subunits/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ ├── androidTest/ │ │ └── java/ │ │ └── me/ │ │ └── jessyan/ │ │ └── autosize/ │ │ └── demo/ │ │ └── ExampleInstrumentedTest.java │ ├── main/ │ │ ├── AndroidManifest.xml │ │ ├── java/ │ │ │ └── me/ │ │ │ └── jessyan/ │ │ │ └── autosize/ │ │ │ └── demo/ │ │ │ └── subunits/ │ │ │ ├── BaseApplication.java │ │ │ ├── CustomAdaptActivity.java │ │ │ └── MainActivity.java │ │ └── res/ │ │ ├── drawable/ │ │ │ └── ic_launcher_background.xml │ │ ├── drawable-v24/ │ │ │ └── ic_launcher_foreground.xml │ │ ├── layout/ │ │ │ ├── activity_custom_adapt.xml │ │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26/ │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ └── values/ │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test/ │ └── java/ │ └── me/ │ └── jessyan/ │ └── autosize/ │ └── demo/ │ └── ExampleUnitTest.java ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat └── settings.gradle ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/ISSUE_TEMPLATE.md ================================================ ### Environment - [x] Autosize Version: - [x] Target Android Version: - [x] Device Model: - [x] Device Resolution: - [x] Design Size On AndroidManifest: ### Bug Description: ### Log: ```log ``` ### Screenshot ### Related Code: ```java ``` ### Others: ================================================ FILE: .gitignore ================================================ # Built application files *.apk *.ap_ # Files for the ART/Dalvik VM *.dex # Java class files *.class # Generated files bin/ gen/ out/ # Gradle files .gradle/ build/ # Local configuration file (sdk path, etc) local.properties # Proguard folder generated by Eclipse proguard/ # Log Files *.log # Android Studio Navigation editor temp files .navigation/ # Android Studio captures folder captures/ # Intellij *.iml .idea # Keystore files *.jks # MacOS .DS_Store ================================================ FILE: .travis.yml ================================================ language: android jdk: oraclejdk8 before_install: - yes | sdkmanager "platforms;android-29" env: global: - ANDROID_API_LEVEL=29 - ANDROID_BUILD_TOOLS_VERSION=29.0.2 - TRAVIS_SECURE_ENV_VARS=true android: components: # The BuildTools version used by your project - tools - platform-tools - build-tools-$ANDROID_BUILD_TOOLS_VERSION - extra-android-m2repository - extra-google-android-support # The SDK version used to compile your project - android-$ANDROID_API_LEVEL licenses: - '.+' script: - ./gradlew clean - ./gradlew assembleDebug ================================================ FILE: CHANGELOG.md ================================================ [ChangeLog](https://github.com/JessYanCoding/AndroidAutoSize/releases) ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README-zh.md ================================================  
## 今日头条屏幕适配方案终极版,一个极低成本的 Android 屏幕适配方案. ## Overview ### Pixel 2 XL | 1440 x 2880 | 560dpi:
* Created by JessYan on 2018/8/8 14:32 * Contact me * Follow me * ================================================ */ public class ActivityLifecycleCallbacksImpl implements Application.ActivityLifecycleCallbacks { /** * 屏幕适配逻辑策略类 */ private AutoAdaptStrategy mAutoAdaptStrategy; /** * 让 Fragment 支持自定义适配参数 */ private FragmentLifecycleCallbacksImpl mFragmentLifecycleCallbacks; private FragmentLifecycleCallbacksImplToAndroidx mFragmentLifecycleCallbacksToAndroidx; public ActivityLifecycleCallbacksImpl(AutoAdaptStrategy autoAdaptStrategy) { if (DEPENDENCY_ANDROIDX) { mFragmentLifecycleCallbacksToAndroidx = new FragmentLifecycleCallbacksImplToAndroidx(autoAdaptStrategy); } else if (DEPENDENCY_SUPPORT){ mFragmentLifecycleCallbacks = new FragmentLifecycleCallbacksImpl(autoAdaptStrategy); } mAutoAdaptStrategy = autoAdaptStrategy; } @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { if (AutoSizeConfig.getInstance().isCustomFragment()) { if (mFragmentLifecycleCallbacksToAndroidx != null && activity instanceof androidx.fragment.app.FragmentActivity) { ((androidx.fragment.app.FragmentActivity) activity).getSupportFragmentManager().registerFragmentLifecycleCallbacks(mFragmentLifecycleCallbacksToAndroidx, true); } else if (mFragmentLifecycleCallbacks != null && activity instanceof android.support.v4.app.FragmentActivity) { ((android.support.v4.app.FragmentActivity) activity).getSupportFragmentManager().registerFragmentLifecycleCallbacks(mFragmentLifecycleCallbacks, true); } } //Activity 中的 setContentView(View) 一定要在 super.onCreate(Bundle); 之后执行 if (mAutoAdaptStrategy != null) { mAutoAdaptStrategy.applyAdapt(activity, activity); } } @Override public void onActivityStarted(Activity activity) { if (mAutoAdaptStrategy != null) { mAutoAdaptStrategy.applyAdapt(activity, activity); } } @Override public void onActivityResumed(Activity activity) { } @Override public void onActivityPaused(Activity activity) { } @Override public void onActivityStopped(Activity activity) { } @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) { } @Override public void onActivityDestroyed(Activity activity) { } /** * 设置屏幕适配逻辑策略类 * * @param autoAdaptStrategy {@link AutoAdaptStrategy} */ public void setAutoAdaptStrategy(AutoAdaptStrategy autoAdaptStrategy) { mAutoAdaptStrategy = autoAdaptStrategy; if (mFragmentLifecycleCallbacksToAndroidx != null) { mFragmentLifecycleCallbacksToAndroidx.setAutoAdaptStrategy(autoAdaptStrategy); } else if (mFragmentLifecycleCallbacks != null) { mFragmentLifecycleCallbacks.setAutoAdaptStrategy(autoAdaptStrategy); } } } ================================================ FILE: autosize/src/main/java/me/jessyan/autosize/AutoAdaptStrategy.java ================================================ /* * Copyright 2018 JessYan * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package me.jessyan.autosize; import android.app.Activity; import android.app.Application; import android.util.DisplayMetrics; /** * ================================================ * 屏幕适配逻辑策略类, 可通过 {@link AutoSizeConfig#init(Application, boolean, AutoAdaptStrategy)} * 和 {@link AutoSizeConfig#setAutoAdaptStrategy(AutoAdaptStrategy)} 切换策略 * * @see DefaultAutoAdaptStrategy * Created by JessYan on 2018/8/9 15:13 * Contact me * Follow me * ================================================ */ public interface AutoAdaptStrategy { /** * 开始执行屏幕适配逻辑 * * @param target 需要屏幕适配的对象 (可能是 {@link Activity} 或者 Fragment) * @param activity 需要拿到当前的 {@link Activity} 才能修改 {@link DisplayMetrics#density} */ void applyAdapt(Object target, Activity activity); } ================================================ FILE: autosize/src/main/java/me/jessyan/autosize/AutoSize.java ================================================ /* * Copyright 2018 JessYan * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package me.jessyan.autosize; import android.app.Activity; import android.app.Application; import android.app.Dialog; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; import android.net.Uri; import android.util.DisplayMetrics; import android.util.SparseArray; import android.view.View; import java.util.Locale; import me.jessyan.autosize.external.ExternalAdaptInfo; import me.jessyan.autosize.external.ExternalAdaptManager; import me.jessyan.autosize.internal.CancelAdapt; import me.jessyan.autosize.internal.CustomAdapt; import me.jessyan.autosize.utils.AutoSizeLog; import me.jessyan.autosize.utils.Preconditions; /** * ================================================ * AndroidAutoSize 用于屏幕适配的核心方法都在这里, 核心原理来自于 今日头条官方适配方案 * 此方案只要应用到 {@link Activity} 上, 这个 {@link Activity} 下的所有 Fragment、{@link Dialog}、 * 自定义 {@link View} 都会达到适配的效果, 如果某个页面不想使用适配请让该 {@link Activity} 实现 {@link CancelAdapt} *
* 任何方案都不可能完美, 在成本和收益中做出取舍, 选择出最适合自己的方案即可, 在没有更好的方案出来之前, 只有继续忍耐它的不完美, 或者自己作出改变 * 既然选择, 就不要抱怨, 感谢 今日头条技术团队 和 张鸿洋 等人对 Android 屏幕适配领域的的贡献 *
* Created by JessYan on 2018/8/8 19:20
* Contact me
* Follow me
* ================================================
*/
public final class AutoSize {
private static SparseArray
* Created by JessYan on 2018/8/8 19:20
* Contact me
* Follow me
* ================================================
*/
public final class AutoSizeCompat {
private static SparseArray
* Created by JessYan on 2018/8/8 09:58
* Contact me
* Follow me
* ================================================
*/
public final class AutoSizeConfig {
private static volatile AutoSizeConfig sInstance;
private static final String KEY_DESIGN_WIDTH_IN_DP = "design_width_in_dp";
private static final String KEY_DESIGN_HEIGHT_IN_DP = "design_height_in_dp";
public static final boolean DEPENDENCY_ANDROIDX;
public static final boolean DEPENDENCY_SUPPORT;
private Application mApplication;
/**
* 用来管理外部三方库 {@link Activity} 的适配
*/
private ExternalAdaptManager mExternalAdaptManager = new ExternalAdaptManager();
/**
* 用来管理 AndroidAutoSize 支持的所有单位, AndroidAutoSize 支持五种单位 (dp、sp、pt、in、mm)
*/
private UnitsManager mUnitsManager = new UnitsManager();
/**
* 最初的 {@link DisplayMetrics#density}
*/
private float mInitDensity = -1;
/**
* 最初的 {@link DisplayMetrics#densityDpi}
*/
private int mInitDensityDpi;
/**
* 最初的 {@link DisplayMetrics#scaledDensity}
*/
private float mInitScaledDensity;
/**
* 最初的 {@link DisplayMetrics#xdpi}
*/
private float mInitXdpi;
/**
* 最初的 {@link Configuration#screenWidthDp}
*/
private int mInitScreenWidthDp;
/**
* 最初的 {@link Configuration#screenHeightDp}
*/
private int mInitScreenHeightDp;
/**
* 设计图上的总宽度, 单位 dp
*/
private int mDesignWidthInDp;
/**
* 设计图上的总高度, 单位 dp
*/
private int mDesignHeightInDp;
/**
* 设备的屏幕总宽度, 单位 px
*/
private int mScreenWidth;
/**
* 设备的屏幕总高度, 单位 px, 如果 {@link #isUseDeviceSize} 为 {@code false}, 屏幕总高度会减去状态栏的高度
*/
private int mScreenHeight;
/**
* 状态栏高度, 当 {@link #isUseDeviceSize} 为 {@code false} 时, AndroidAutoSize 会将 {@link #mScreenHeight} 减去状态栏高度
* AndroidAutoSize 默认使用 {@link ScreenUtils#getStatusBarHeight()} 方法获取状态栏高度
* AndroidAutoSize 使用者可使用 {@link #setStatusBarHeight(int)} 自行设置状态栏高度
*/
private int mStatusBarHeight;
/**
* 为了保证在不同高宽比的屏幕上显示效果也能完全一致, 所以本方案适配时是以设计图宽度与设备实际宽度的比例或设计图高度与设备实际高度的比例应用到
* 每个 View 上 (只能在宽度和高度之中选一个作为基准), 从而使每个 View 的高和宽用同样的比例缩放, 避免在与设计图高宽比不一致的设备上出现适配的 View 高或宽变形的问题
* {@link #isBaseOnWidth} 为 {@code true} 时代表以宽度等比例缩放, {@code false} 代表以高度等比例缩放
* {@link #isBaseOnWidth} 为全局配置, 默认为 {@code true}, 每个 {@link Activity} 也可以单独选择使用高或者宽做等比例缩放
*/
private boolean isBaseOnWidth = true;
/**
* 此字段表示是否使用设备的实际尺寸做适配
* {@link #isUseDeviceSize} 为 {@code true} 表示屏幕高度 {@link #mScreenHeight} 包含状态栏的高度
* {@link #isUseDeviceSize} 为 {@code false} 表示 {@link #mScreenHeight} 会减去状态栏的高度, 默认为 {@code true}
*/
private boolean isUseDeviceSize = true;
/**
* {@link #mActivityLifecycleCallbacks} 可用来代替在 BaseActivity 中加入适配代码的传统方式
* {@link #mActivityLifecycleCallbacks} 这种方案类似于 AOP, 面向接口, 侵入性低, 方便统一管理, 扩展性强, 并且也支持适配三方库的 {@link Activity}
*/
private ActivityLifecycleCallbacksImpl mActivityLifecycleCallbacks;
/**
* 框架具有 热插拔 特性, 支持在项目运行中动态停止和重新启动适配功能
*
* @see #stop(Activity)
* @see #restart()
*/
private boolean isStop;
/**
* 是否让框架支持自定义 Fragment 的适配参数, 由于这个需求是比较少见的, 所以须要使用者手动开启
*/
private boolean isCustomFragment;
/**
* 屏幕方向, {@code true} 为纵向, {@code false} 为横向
*/
private boolean isVertical;
/**
* 是否屏蔽系统字体大小对 AndroidAutoSize 的影响, 如果为 {@code true}, App 内的字体的大小将不会跟随系统设置中字体大小的改变
* 如果为 {@code false}, 则会跟随系统设置中字体大小的改变, 默认为 {@code false}
*/
private boolean isExcludeFontScale;
/**
* 区别于系统字体大小的放大比例, AndroidAutoSize 允许 APP 内部可以独立于系统字体大小之外,独自拥有全局调节 APP 字体大小的能力
* 当然, 在 APP 内您必须使用 sp 来作为字体的单位, 否则此功能无效, 将此值设为 0 则取消此功能
*/
private float privateFontScale;
/**
* 是否是 Miui 系统
*/
private boolean isMiui;
/**
* Miui 系统中的 mTmpMetrics 字段
*/
private Field mTmpMetricsField;
/**
* 屏幕适配监听器,用于监听屏幕适配时的一些事件
*/
private onAdaptListener mOnAdaptListener;
static {
DEPENDENCY_ANDROIDX = findClassByClassName("androidx.fragment.app.FragmentActivity");
DEPENDENCY_SUPPORT = findClassByClassName("android.support.v4.app.FragmentActivity");
}
private static boolean findClassByClassName(String className) {
boolean hasDependency;
try {
Class.forName(className);
hasDependency = true;
} catch (ClassNotFoundException e) {
hasDependency = false;
}
return hasDependency;
}
public static AutoSizeConfig getInstance() {
if (sInstance == null) {
synchronized (AutoSizeConfig.class) {
if (sInstance == null) {
sInstance = new AutoSizeConfig();
}
}
}
return sInstance;
}
private AutoSizeConfig() {
}
public Application getApplication() {
Preconditions.checkNotNull(mApplication, "Please call the AutoSizeConfig#init() first");
return mApplication;
}
/**
* v0.7.0 以后, 框架会在 APP 启动时自动调用此方法进行初始化, 使用者无需手动初始化, 初始化方法只能调用一次, 否则报错
* 此方法默认使用以宽度进行等比例适配, 如想使用以高度进行等比例适配, 请调用 {@link #init(Application, boolean)}
*
* @param application {@link Application}
*/
AutoSizeConfig init(Application application) {
return init(application, true, null);
}
/**
* v0.7.0 以后, 框架会在 APP 启动时自动调用此方法进行初始化, 使用者无需手动初始化, 初始化方法只能调用一次, 否则报错
* 此方法使用默认的 {@link AutoAdaptStrategy} 策略, 如想使用自定义的 {@link AutoAdaptStrategy} 策略
* 请调用 {@link #init(Application, boolean, AutoAdaptStrategy)}
*
* @param application {@link Application}
* @param isBaseOnWidth 详情请查看 {@link #isBaseOnWidth} 的注释
*/
AutoSizeConfig init(Application application, boolean isBaseOnWidth) {
return init(application, isBaseOnWidth, null);
}
/**
* v0.7.0 以后, 框架会在 APP 启动时自动调用此方法进行初始化, 使用者无需手动初始化, 初始化方法只能调用一次, 否则报错
*
* @param application {@link Application}
* @param isBaseOnWidth 详情请查看 {@link #isBaseOnWidth} 的注释
* @param strategy {@link AutoAdaptStrategy}, 传 {@code null} 则使用 {@link DefaultAutoAdaptStrategy}
*/
AutoSizeConfig init(final Application application, boolean isBaseOnWidth, AutoAdaptStrategy strategy) {
Preconditions.checkArgument(mInitDensity == -1, "AutoSizeConfig#init() can only be called once");
Preconditions.checkNotNull(application, "application == null");
this.mApplication = application;
this.isBaseOnWidth = isBaseOnWidth;
final DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
final Configuration configuration = Resources.getSystem().getConfiguration();
//设置一个默认值, 避免在低配设备上因为获取 MetaData 过慢, 导致适配时未能正常获取到设计图尺寸
//建议使用者在低配设备上主动在 Application#onCreate 中调用 setDesignWidthInDp 替代以使用 AndroidManifest 配置设计图尺寸的方式
if (AutoSizeConfig.getInstance().getUnitsManager().getSupportSubunits() == Subunits.NONE) {
mDesignWidthInDp = 360;
mDesignHeightInDp = 640;
} else {
mDesignWidthInDp = 1080;
mDesignHeightInDp = 1920;
}
getMetaData(application);
isVertical = application.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
int[] screenSize = ScreenUtils.getScreenSize(application);
mScreenWidth = screenSize[0];
mScreenHeight = screenSize[1];
mStatusBarHeight = ScreenUtils.getStatusBarHeight();
AutoSizeLog.d("designWidthInDp = " + mDesignWidthInDp + ", designHeightInDp = " + mDesignHeightInDp + ", screenWidth = " + mScreenWidth + ", screenHeight = " + mScreenHeight);
mInitDensity = displayMetrics.density;
mInitDensityDpi = displayMetrics.densityDpi;
mInitScaledDensity = displayMetrics.scaledDensity;
mInitXdpi = displayMetrics.xdpi;
mInitScreenWidthDp = configuration.screenWidthDp;
mInitScreenHeightDp = configuration.screenHeightDp;
application.registerComponentCallbacks(new ComponentCallbacks() {
@Override
public void onConfigurationChanged(Configuration newConfig) {
if (newConfig != null) {
if (newConfig.fontScale > 0) {
mInitScaledDensity =
Resources.getSystem().getDisplayMetrics().scaledDensity;
AutoSizeLog.d("initScaledDensity = " + mInitScaledDensity + " on ConfigurationChanged");
}
isVertical = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT;
int[] screenSize = ScreenUtils.getScreenSize(application);
mScreenWidth = screenSize[0];
mScreenHeight = screenSize[1];
}
}
@Override
public void onLowMemory() {
}
});
AutoSizeLog.d("initDensity = " + mInitDensity + ", initScaledDensity = " + mInitScaledDensity);
mActivityLifecycleCallbacks = new ActivityLifecycleCallbacksImpl(new WrapperAutoAdaptStrategy(strategy == null ? new DefaultAutoAdaptStrategy() : strategy));
application.registerActivityLifecycleCallbacks(mActivityLifecycleCallbacks);
if ("MiuiResources".equals(application.getResources().getClass().getSimpleName()) || "XResources".equals(application.getResources().getClass().getSimpleName())) {
isMiui = true;
try {
mTmpMetricsField = Resources.class.getDeclaredField("mTmpMetrics");
mTmpMetricsField.setAccessible(true);
} catch (Exception e) {
mTmpMetricsField = null;
}
}
return this;
}
/**
* 重新开始框架的运行
* 框架具有 热插拔 特性, 支持在项目运行中动态停止和重新启动适配功能
*/
public void restart() {
Preconditions.checkNotNull(mActivityLifecycleCallbacks, "Please call the AutoSizeConfig#init() first");
synchronized (AutoSizeConfig.class) {
if (isStop) {
mApplication.registerActivityLifecycleCallbacks(mActivityLifecycleCallbacks);
isStop = false;
}
}
}
/**
* 停止框架的运行
* 框架具有 热插拔 特性, 支持在项目运行中动态停止和重新启动适配功能
*/
public void stop(Activity activity) {
Preconditions.checkNotNull(mActivityLifecycleCallbacks, "Please call the AutoSizeConfig#init() first");
synchronized (AutoSizeConfig.class) {
if (!isStop) {
mApplication.unregisterActivityLifecycleCallbacks(mActivityLifecycleCallbacks);
AutoSize.cancelAdapt(activity);
isStop = true;
}
}
}
/**
* 设置屏幕适配逻辑策略类
*
* @param autoAdaptStrategy {@link AutoAdaptStrategy}
*/
public AutoSizeConfig setAutoAdaptStrategy(AutoAdaptStrategy autoAdaptStrategy) {
Preconditions.checkNotNull(autoAdaptStrategy, "autoAdaptStrategy == null");
Preconditions.checkNotNull(mActivityLifecycleCallbacks, "Please call the AutoSizeConfig#init() first");
mActivityLifecycleCallbacks.setAutoAdaptStrategy(new WrapperAutoAdaptStrategy(autoAdaptStrategy));
return this;
}
/**
* 设置屏幕适配监听器
*
* @param onAdaptListener {@link onAdaptListener}
*/
public AutoSizeConfig setOnAdaptListener(onAdaptListener onAdaptListener) {
Preconditions.checkNotNull(onAdaptListener, "onAdaptListener == null");
mOnAdaptListener = onAdaptListener;
return this;
}
/**
* 是否全局按照宽度进行等比例适配
*
* @param baseOnWidth {@code true} 为按照宽度, {@code false} 为按照高度
* @see #isBaseOnWidth 详情请查看这个字段的注释
*/
public AutoSizeConfig setBaseOnWidth(boolean baseOnWidth) {
isBaseOnWidth = baseOnWidth;
return this;
}
/**
* 是否使用设备的实际尺寸做适配
*
* @param useDeviceSize {@code true} 为使用设备的实际尺寸 (包含状态栏), {@code false} 为不使用设备的实际尺寸 (不包含状态栏)
* @see #isUseDeviceSize 详情请查看这个字段的注释
*/
public AutoSizeConfig setUseDeviceSize(boolean useDeviceSize) {
isUseDeviceSize = useDeviceSize;
return this;
}
/**
* 是否打印 Log
*
* @param log {@code true} 为打印
*/
public AutoSizeConfig setLog(boolean log) {
AutoSizeLog.setDebug(log);
return this;
}
/**
* 是否让框架支持自定义 Fragment 的适配参数, 由于这个需求是比较少见的, 所以须要使用者手动开启
*
* @param customFragment {@code true} 为支持
*/
public AutoSizeConfig setCustomFragment(boolean customFragment) {
isCustomFragment = customFragment;
return this;
}
/**
* 框架是否已经开启支持自定义 Fragment 的适配参数
*
* @return {@code true} 为支持
*/
public boolean isCustomFragment() {
return isCustomFragment;
}
/**
* 框架是否已经停止运行
*
* @return {@code false} 框架正在运行, {@code true} 框架已经停止运行
*/
public boolean isStop() {
return isStop;
}
/**
* {@link ExternalAdaptManager} 用来管理外部三方库 {@link Activity} 的适配
*
* @return {@link #mExternalAdaptManager}
*/
public ExternalAdaptManager getExternalAdaptManager() {
return mExternalAdaptManager;
}
/**
* {@link UnitsManager} 用来管理 AndroidAutoSize 支持的所有单位, AndroidAutoSize 支持五种单位 (dp、sp、pt、in、mm)
*
* @return {@link #mUnitsManager}
*/
public UnitsManager getUnitsManager() {
return mUnitsManager;
}
/**
* 返回 {@link #mOnAdaptListener}
*
* @return {@link #mOnAdaptListener}
*/
public onAdaptListener getOnAdaptListener() {
return mOnAdaptListener;
}
/**
* 返回 {@link #isBaseOnWidth}
*
* @return {@link #isBaseOnWidth}
*/
public boolean isBaseOnWidth() {
return isBaseOnWidth;
}
/**
* 返回 {@link #isUseDeviceSize}
*
* @return {@link #isUseDeviceSize}
*/
public boolean isUseDeviceSize() {
return isUseDeviceSize;
}
/**
* 返回 {@link #mScreenWidth}
*
* @return {@link #mScreenWidth}
*/
public int getScreenWidth() {
return mScreenWidth;
}
/**
* 返回 {@link #mScreenHeight}
*
* @return {@link #mScreenHeight}
*/
public int getScreenHeight() {
return isUseDeviceSize() ? mScreenHeight : mScreenHeight - mStatusBarHeight;
}
/**
* 获取 {@link #mDesignWidthInDp}
*
* @return {@link #mDesignWidthInDp}
*/
public int getDesignWidthInDp() {
Preconditions.checkArgument(mDesignWidthInDp > 0, "you must set " + KEY_DESIGN_WIDTH_IN_DP + " in your AndroidManifest file");
return mDesignWidthInDp;
}
/**
* 获取 {@link #mDesignHeightInDp}
*
* @return {@link #mDesignHeightInDp}
*/
public int getDesignHeightInDp() {
Preconditions.checkArgument(mDesignHeightInDp > 0, "you must set " + KEY_DESIGN_HEIGHT_IN_DP + " in your AndroidManifest file");
return mDesignHeightInDp;
}
/**
* 获取 {@link #mInitDensity}
*
* @return {@link #mInitDensity}
*/
public float getInitDensity() {
return mInitDensity;
}
/**
* 获取 {@link #mInitDensityDpi}
*
* @return {@link #mInitDensityDpi}
*/
public int getInitDensityDpi() {
return mInitDensityDpi;
}
/**
* 获取 {@link #mInitScaledDensity}
*
* @return {@link #mInitScaledDensity}
*/
public float getInitScaledDensity() {
return mInitScaledDensity;
}
/**
* 获取 {@link #mInitXdpi}
*
* @return {@link #mInitXdpi}
*/
public float getInitXdpi() {
return mInitXdpi;
}
/**
* 获取 {@link #mInitScreenWidthDp}
*
* @return {@link #mInitScreenWidthDp}
*/
public int getInitScreenWidthDp() {
return mInitScreenWidthDp;
}
/**
* 获取 {@link #mInitScreenHeightDp}
*
* @return {@link #mInitScreenHeightDp}
*/
public int getInitScreenHeightDp() {
return mInitScreenHeightDp;
}
/**
* 获取屏幕方向
*
* @return {@code true} 为纵向, {@code false} 为横向
*/
public boolean isVertical() {
return isVertical;
}
/**
* 返回 {@link #isMiui}
*
* @return {@link #isMiui}
*/
public boolean isMiui() {
return isMiui;
}
/**
* 返回 {@link #mTmpMetricsField}
*
* @return {@link #mTmpMetricsField}
*/
public Field getTmpMetricsField() {
return mTmpMetricsField;
}
/**
* 设置屏幕方向
*
* @param vertical {@code true} 为纵向, {@code false} 为横向
*/
public AutoSizeConfig setVertical(boolean vertical) {
isVertical = vertical;
return this;
}
/**
* 是否屏蔽系统字体大小对 AndroidAutoSize 的影响, 如果为 {@code true}, App 内的字体的大小将不会跟随系统设置中字体大小的改变
* 如果为 {@code false}, 则会跟随系统设置中字体大小的改变, 默认为 {@code false}
*
* @return {@link #isExcludeFontScale}
*/
public boolean isExcludeFontScale() {
return isExcludeFontScale;
}
/**
* 是否屏蔽系统字体大小对 AndroidAutoSize 的影响, 如果为 {@code true}, App 内的字体的大小将不会跟随系统设置中字体大小的改变
* 如果为 {@code false}, 则会跟随系统设置中字体大小的改变, 默认为 {@code false}
*
* @param excludeFontScale 是否屏蔽
*/
public AutoSizeConfig setExcludeFontScale(boolean excludeFontScale) {
isExcludeFontScale = excludeFontScale;
return this;
}
/**
* 区别于系统字体大小的放大比例, AndroidAutoSize 允许 APP 内部可以独立于系统字体大小之外,独自拥有全局调节 APP 字体大小的能力
* 当然, 在 APP 内您必须使用 sp 来作为字体的单位, 否则此功能无效
*
* @param fontScale 字体大小放大的比例, 设为 0 则取消此功能
*/
public AutoSizeConfig setPrivateFontScale(float fontScale) {
privateFontScale = fontScale;
return this;
}
/**
* 区别于系统字体大小的放大比例, AndroidAutoSize 允许 APP 内部可以独立于系统字体大小之外,独自拥有全局调节 APP 字体大小的能力
* 当然, 在 APP 内您必须使用 sp 来作为字体的单位, 否则此功能无效
*
* @return 私有的字体大小放大比例
*/
public float getPrivateFontScale() {
return privateFontScale;
}
/**
* 设置屏幕宽度
*
* @param screenWidth 屏幕宽度
*/
public AutoSizeConfig setScreenWidth(int screenWidth) {
Preconditions.checkArgument(screenWidth > 0, "screenWidth must be > 0");
mScreenWidth = screenWidth;
return this;
}
/**
* 设置屏幕高度
*
* @param screenHeight 屏幕高度 (需要包含状态栏)
*/
public AutoSizeConfig setScreenHeight(int screenHeight) {
Preconditions.checkArgument(screenHeight > 0, "screenHeight must be > 0");
mScreenHeight = screenHeight;
return this;
}
/**
* 设置全局设计图宽度
*
* @param designWidthInDp 设计图宽度
*/
public AutoSizeConfig setDesignWidthInDp(int designWidthInDp) {
Preconditions.checkArgument(designWidthInDp > 0, "designWidthInDp must be > 0");
mDesignWidthInDp = designWidthInDp;
return this;
}
/**
* 设置全局设计图高度
*
* @param designHeightInDp 设计图高度
*/
public AutoSizeConfig setDesignHeightInDp(int designHeightInDp) {
Preconditions.checkArgument(designHeightInDp > 0, "designHeightInDp must be > 0");
mDesignHeightInDp = designHeightInDp;
return this;
}
/**
* 设置状态栏高度
*
* @param statusBarHeight 状态栏高度
*/
public AutoSizeConfig setStatusBarHeight(int statusBarHeight) {
Preconditions.checkArgument(statusBarHeight > 0, "statusBarHeight must be > 0");
mStatusBarHeight = statusBarHeight;
return this;
}
/**
* 获取使用者在 AndroidManifest 中填写的 Meta 信息
*
* Example usage:
*
* Created by JessYan on 2018/8/11 16:42
* Contact me
* Follow me
* ================================================
*/
public class DisplayMetricsInfo implements Parcelable {
private float density;
private int densityDpi;
private float scaledDensity;
private float xdpi;
private int screenWidthDp;
private int screenHeightDp;
public DisplayMetricsInfo(float density, int densityDpi, float scaledDensity, float xdpi) {
this.density = density;
this.densityDpi = densityDpi;
this.scaledDensity = scaledDensity;
this.xdpi = xdpi;
}
public DisplayMetricsInfo(float density, int densityDpi, float scaledDensity, float xdpi, int screenWidthDp, int screenHeightDp) {
this.density = density;
this.densityDpi = densityDpi;
this.scaledDensity = scaledDensity;
this.xdpi = xdpi;
this.screenWidthDp = screenWidthDp;
this.screenHeightDp = screenHeightDp;
}
public float getDensity() {
return density;
}
public void setDensity(float density) {
this.density = density;
}
public int getDensityDpi() {
return densityDpi;
}
public void setDensityDpi(int densityDpi) {
this.densityDpi = densityDpi;
}
public float getScaledDensity() {
return scaledDensity;
}
public void setScaledDensity(float scaledDensity) {
this.scaledDensity = scaledDensity;
}
public float getXdpi() {
return xdpi;
}
public void setXdpi(float xdpi) {
this.xdpi = xdpi;
}
public int getScreenWidthDp() {
return screenWidthDp;
}
public void setScreenWidthDp(int screenWidthDp) {
this.screenWidthDp = screenWidthDp;
}
public int getScreenHeightDp() {
return screenHeightDp;
}
public void setScreenHeightDp(int screenHeightDp) {
this.screenHeightDp = screenHeightDp;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeFloat(this.density);
dest.writeInt(this.densityDpi);
dest.writeFloat(this.scaledDensity);
dest.writeFloat(this.xdpi);
dest.writeInt(this.screenWidthDp);
dest.writeInt(this.screenHeightDp);
}
protected DisplayMetricsInfo(Parcel in) {
this.density = in.readFloat();
this.densityDpi = in.readInt();
this.scaledDensity = in.readFloat();
this.xdpi = in.readFloat();
this.screenWidthDp = in.readInt();
this.screenHeightDp = in.readInt();
}
public static final Creator
* Created by JessYan on 2018/8/25 13:52
* Contact me
* Follow me
* ================================================
*/
public class FragmentLifecycleCallbacksImpl extends FragmentManager.FragmentLifecycleCallbacks {
/**
* 屏幕适配逻辑策略类
*/
private AutoAdaptStrategy mAutoAdaptStrategy;
public FragmentLifecycleCallbacksImpl(AutoAdaptStrategy autoAdaptStrategy) {
mAutoAdaptStrategy = autoAdaptStrategy;
}
@Override
public void onFragmentCreated(FragmentManager fm, Fragment f, Bundle savedInstanceState) {
if (mAutoAdaptStrategy != null) {
mAutoAdaptStrategy.applyAdapt(f, f.getActivity());
}
}
/**
* 设置屏幕适配逻辑策略类
*
* @param autoAdaptStrategy {@link AutoAdaptStrategy}
*/
public void setAutoAdaptStrategy(AutoAdaptStrategy autoAdaptStrategy) {
mAutoAdaptStrategy = autoAdaptStrategy;
}
}
================================================
FILE: autosize/src/main/java/me/jessyan/autosize/FragmentLifecycleCallbacksImplToAndroidx.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
/**
* ================================================
* {@link FragmentLifecycleCallbacksImplToAndroidx} 可用来代替在 BaseFragment 中加入适配代码的传统方式
* {@link FragmentLifecycleCallbacksImplToAndroidx} 这种方案类似于 AOP, 面向接口, 侵入性低, 方便统一管理, 扩展性强, 并且也支持适配三方库的 {@link Fragment}
*
* Created by JessYan on 2018/8/25 13:52
* Contact me
* Follow me
* ================================================
*/
public class FragmentLifecycleCallbacksImplToAndroidx extends FragmentManager.FragmentLifecycleCallbacks {
/**
* 屏幕适配逻辑策略类
*/
private AutoAdaptStrategy mAutoAdaptStrategy;
public FragmentLifecycleCallbacksImplToAndroidx(AutoAdaptStrategy autoAdaptStrategy) {
mAutoAdaptStrategy = autoAdaptStrategy;
}
@Override
public void onFragmentCreated(FragmentManager fm, Fragment f, Bundle savedInstanceState) {
if (mAutoAdaptStrategy != null) {
mAutoAdaptStrategy.applyAdapt(f, f.getActivity());
}
}
/**
* 设置屏幕适配逻辑策略类
*
* @param autoAdaptStrategy {@link AutoAdaptStrategy}
*/
public void setAutoAdaptStrategy(AutoAdaptStrategy autoAdaptStrategy) {
mAutoAdaptStrategy = autoAdaptStrategy;
}
}
================================================
FILE: autosize/src/main/java/me/jessyan/autosize/InitProvider.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize;
import android.content.Context;
import android.app.Application;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import me.jessyan.autosize.utils.AutoSizeUtils;
/**
* ================================================
* 通过声明 {@link ContentProvider} 自动完成初始化
* Created by JessYan on 2018/8/19 11:55
* Contact me
* Follow me
* ================================================
*/
public class InitProvider extends ContentProvider {
@Override
public boolean onCreate() {
Context application = getContext().getApplicationContext();
if (application == null) {
application = AutoSizeUtils.getApplicationByReflect();
}
AutoSizeConfig.getInstance()
.setLog(true)
.init((Application) application)
.setUseDeviceSize(false);
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
return null;
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return 0;
}
}
================================================
FILE: autosize/src/main/java/me/jessyan/autosize/WrapperAutoAdaptStrategy.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize;
import android.app.Activity;
/**
* ================================================
* {@link AutoAdaptStrategy} 的包装者, 用于给 {@link AutoAdaptStrategy} 的实现类增加一些额外的职责
*
* Created by JessYan on 2018/10/30 15:07
* Contact me
* Follow me
* ================================================
*/
public class WrapperAutoAdaptStrategy implements AutoAdaptStrategy {
private final AutoAdaptStrategy mAutoAdaptStrategy;
public WrapperAutoAdaptStrategy(AutoAdaptStrategy autoAdaptStrategy) {
mAutoAdaptStrategy = autoAdaptStrategy;
}
@Override
public void applyAdapt(Object target, Activity activity) {
onAdaptListener onAdaptListener = AutoSizeConfig.getInstance().getOnAdaptListener();
if (onAdaptListener != null){
onAdaptListener.onAdaptBefore(target, activity);
}
if (mAutoAdaptStrategy != null) {
mAutoAdaptStrategy.applyAdapt(target, activity);
}
if (onAdaptListener != null){
onAdaptListener.onAdaptAfter(target, activity);
}
}
}
================================================
FILE: autosize/src/main/java/me/jessyan/autosize/external/ExternalAdaptInfo.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize.external;
import android.app.Activity;
import android.os.Parcel;
import android.os.Parcelable;
/**
* ================================================
* {@link ExternalAdaptInfo} 用来存储外部三方库的适配参数, 因为 AndroidAutoSize 默认会对项目中的所有模块都进行适配
* 三方库的 {@link Activity} 也不例外, 但三方库的适配参数可能和自己项目中的适配参数不一致, 导致三方库的适配效果和理想的效果差别很大
* 所以需要向 AndroidAutoSize 提供三方库的适配参数, 已完成对三方库的屏幕适配
*
* Created by JessYan on 2018/8/9 18:19
* Contact me
* Follow me
* ================================================
*/
public class ExternalAdaptInfo implements Parcelable {
/**
* 是否按照宽度进行等比例适配 (为了保证在高宽比不同的屏幕上也能正常适配, 所以只能在宽度和高度之中选一个作为基准进行适配)
* {@code true} 为按照宽度适配, {@code false} 为按照高度适配
*/
private boolean isBaseOnWidth;
/**
* 设计图上的设计尺寸, 单位 dp (三方库页面的设计图尺寸可能无法获知, 所以如果想让三方库的适配效果达到最好, 只有靠不断的尝试)
* {@link #sizeInDp} 须配合 {@link #isBaseOnWidth} 使用, 规则如下:
* 如果 {@link #isBaseOnWidth} 设置为 {@code true}, {@link #sizeInDp} 则应该设置为设计图的总宽度
* 如果 {@link #isBaseOnWidth} 设置为 {@code false}, {@link #sizeInDp} 则应该设置为设计图的总高度
* 如果您不需要自定义设计图上的设计尺寸, 想继续使用在 AndroidManifest 中填写的设计图尺寸, {@link #sizeInDp} 则设置为 {@code 0}
*/
private float sizeInDp;
public ExternalAdaptInfo(boolean isBaseOnWidth) {
this.isBaseOnWidth = isBaseOnWidth;
}
public ExternalAdaptInfo(boolean isBaseOnWidth, float sizeInDp) {
this.isBaseOnWidth = isBaseOnWidth;
this.sizeInDp = sizeInDp;
}
public boolean isBaseOnWidth() {
return isBaseOnWidth;
}
public void setBaseOnWidth(boolean baseOnWidth) {
isBaseOnWidth = baseOnWidth;
}
public float getSizeInDp() {
return sizeInDp;
}
public void setSizeInDp(float sizeInDp) {
this.sizeInDp = sizeInDp;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeByte(this.isBaseOnWidth ? (byte) 1 : (byte) 0);
dest.writeFloat(this.sizeInDp);
}
protected ExternalAdaptInfo(Parcel in) {
this.isBaseOnWidth = in.readByte() != 0;
this.sizeInDp = in.readFloat();
}
public static final Creator
* Created by JessYan on 2018/8/10 14:40
* Contact me
* Follow me
* ================================================
*/
public class ExternalAdaptManager {
private List
* 支持链式调用, 如:
* {@link ExternalAdaptManager#addCancelAdaptOfActivity(Class)#addCancelAdaptOfActivity(Class)}
*
* @param targetClass {@link Activity} class, Fragment class
*/
public synchronized ExternalAdaptManager addCancelAdaptOfActivity(Class> targetClass) {
Preconditions.checkNotNull(targetClass, "targetClass == null");
if (!isRun) {
isRun = true;
}
if (mCancelAdaptList == null) {
mCancelAdaptList = new ArrayList<>();
}
mCancelAdaptList.add(targetClass.getCanonicalName());
return this;
}
/**
* 将需要提供自定义适配参数的三方库 {@link Activity} 添加进来 (但不局限于三方库), 即可让该 {@link Activity} 根据自己提供的适配参数进行适配
* 默认的全局适配参数不能满足您时可以使用此方法
*
* 一般用于三方库的 Activity, 因为三方库的设计图尺寸可能和项目自身的设计图尺寸不一致, 所以要想完美适配三方库的页面
* 就需要提供三方库的设计图尺寸, 以及适配的方向 (以宽为基准还是高为基准?)
* 三方库页面的设计图尺寸可能无法获知, 所以如果想让三方库的适配效果达到最好, 只有靠不断的尝试
* 由于 AndroidAutoSize 可以让布局在所有设备上都等比例缩放, 所以只要您在一个设备上测试出了一个最完美的设计图尺寸
* 那这个三方库页面在其他设备上也会呈现出同样的适配效果, 等比例缩放, 所以也就完成了三方库页面的屏幕适配
* 即使在不改三方库源码的情况下也可以完美适配三方库的页面, 这就是 AndroidAutoSize 的优势
* 但前提是三方库页面的布局使用的是 dp 和 sp, 如果布局全部使用的 px, 那 AndroidAutoSize 也将无能为力
*
* 支持链式调用, 如:
* {@link ExternalAdaptManager#addExternalAdaptInfoOfActivity(Class, ExternalAdaptInfo)#addExternalAdaptInfoOfActivity(Class, ExternalAdaptInfo)}
*
* @param targetClass {@link Activity} class, Fragment class
* @param info {@link ExternalAdaptInfo} 适配参数
*/
public synchronized ExternalAdaptManager addExternalAdaptInfoOfActivity(Class> targetClass, ExternalAdaptInfo info) {
Preconditions.checkNotNull(targetClass, "targetClass == null");
if (!isRun) {
isRun = true;
}
if (mExternalAdaptInfos == null) {
mExternalAdaptInfos = new HashMap<>(16);
}
mExternalAdaptInfos.put(targetClass.getCanonicalName(), info);
return this;
}
/**
* 这个 {@link Activity} 是否存在在取消适配的列表中, 如果在, 则该 {@link Activity} 适配失效
*
* @param targetClass {@link Activity} class, Fragment class
* @return {@code true} 为存在, {@code false} 为不存在
*/
public synchronized boolean isCancelAdapt(Class> targetClass) {
Preconditions.checkNotNull(targetClass, "targetClass == null");
if (mCancelAdaptList == null) {
return false;
}
return mCancelAdaptList.contains(targetClass.getCanonicalName());
}
/**
* 这个 {@link Activity} 是否提供有自定义的适配参数, 如果有则使用此适配参数进行适配
*
* @param targetClass {@link Activity} class, Fragment class
* @return 如果返回 {@code null} 则说明该 {@link Activity} 没有提供自定义的适配参数
*/
public synchronized ExternalAdaptInfo getExternalAdaptInfoOfActivity(Class> targetClass) {
Preconditions.checkNotNull(targetClass, "targetClass == null");
if (mExternalAdaptInfos == null) {
return null;
}
return mExternalAdaptInfos.get(targetClass.getCanonicalName());
}
/**
* 此管理器是否已经启动
*
* @return {@code true} 为已经启动, {@code false} 为没有启动
*/
public boolean isRun() {
return isRun;
}
/**
* 设置管理器的运行状态
*
* @param run {@code true} 为让管理器启动运行, {@code false} 为让管理器停止运行
*/
public ExternalAdaptManager setRun(boolean run) {
isRun = run;
return this;
}
}
================================================
FILE: autosize/src/main/java/me/jessyan/autosize/internal/CancelAdapt.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize.internal;
import android.app.Activity;
/**
* ================================================
* AndroidAutoSize 默认项目中的所有模块都使用适配功能, 三方库的 {@link Activity} 也不例外
* 如果某个页面不想使用适配功能, 请让该页面 {@link Activity} 实现此接口
* 实现此接口表示放弃适配, 所有的适配效果都将失效
*
* Created by JessYan on 2018/8/9 09:54
* Contact me
* Follow me
* ================================================
*/
public interface CancelAdapt {
}
================================================
FILE: autosize/src/main/java/me/jessyan/autosize/internal/CustomAdapt.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize.internal;
import android.app.Activity;
/**
* ================================================
* 如果某些页面不想使用 AndroidAutoSize 初始化时设置的默认适配参数, 请让该页面 {@link Activity} 实现此接口
* 实现此接口即可自定义用于适配的一些参数, 从而影响最终的适配效果
*
* Created by JessYan on 2018/8/9 10:25
* Contact me
* Follow me
* ================================================
*/
public interface CustomAdapt {
/**
* 是否按照宽度进行等比例适配 (为了保证在高宽比不同的屏幕上也能正常适配, 所以只能在宽度和高度之中选一个作为基准进行适配)
*
* @return {@code true} 为按照宽度适配, {@code false} 为按照高度适配
*/
boolean isBaseOnWidth();
/**
* 返回设计图上的设计尺寸, 单位 dp
* {@link #getSizeInDp} 须配合 {@link #isBaseOnWidth()} 使用, 规则如下:
* 如果 {@link #isBaseOnWidth()} 返回 {@code true}, {@link #getSizeInDp} 则应该返回设计图的总宽度
* 如果 {@link #isBaseOnWidth()} 返回 {@code false}, {@link #getSizeInDp} 则应该返回设计图的总高度
* 如果您不需要自定义设计图上的设计尺寸, 想继续使用在 AndroidManifest 中填写的设计图尺寸, {@link #getSizeInDp} 则返回 {@code 0}
*
* @return 设计图上的设计尺寸, 单位 dp
*/
float getSizeInDp();
}
================================================
FILE: autosize/src/main/java/me/jessyan/autosize/onAdaptListener.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize;
import android.app.Activity;
/**
* ================================================
* 屏幕适配监听器,用于监听屏幕适配时的一些事件
*
* Created by JessYan on 2018/10/30 16:29
* Contact me
* Follow me
* ================================================
*/
public interface onAdaptListener {
/**
* 在屏幕适配前调用
*
* @param target 需要屏幕适配的对象 (可能是 {@link Activity} 或者 Fragment)
* @param activity 当前 {@link Activity}
*/
void onAdaptBefore(Object target, Activity activity);
/**
* 在屏幕适配后调用
*
* @param target 需要屏幕适配的对象 (可能是 {@link Activity} 或者 Fragment)
* @param activity 当前 {@link Activity}
*/
void onAdaptAfter(Object target, Activity activity);
}
================================================
FILE: autosize/src/main/java/me/jessyan/autosize/unit/Subunits.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize.unit;
import android.util.DisplayMetrics;
/**
* ================================================
* AndroidAutoSize 支持一些在 Android 系统上比较少见的单位作为副单位, 用于规避修改 {@link DisplayMetrics#density}
* 所造成的对于其他使用 dp 布局的系统控件或三方库控件的不良影响
*
* Created by JessYan on 2018/8/28 10:27
* Contact me
* Follow me
* ================================================
*/
public enum Subunits {
/**
* 不使用副单位
*/
NONE,
/**
* 单位 pt
*
* @see android.util.TypedValue#COMPLEX_UNIT_PT
*/
PT,
/**
* 单位 in
*
* @see android.util.TypedValue#COMPLEX_UNIT_IN
*/
IN,
/**
* 单位 mm
*
* @see android.util.TypedValue#COMPLEX_UNIT_MM
*/
MM
}
================================================
FILE: autosize/src/main/java/me/jessyan/autosize/unit/UnitsManager.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize.unit;
import android.util.DisplayMetrics;
import me.jessyan.autosize.utils.Preconditions;
/**
* ================================================
* 管理 AndroidAutoSize 支持的所有单位, AndroidAutoSize 支持五种单位 (dp、sp、pt、in、mm)
* 其中 dp、sp 这两个是比较常见的单位, 作为 AndroidAutoSize 的主单位, 默认被 AndroidAutoSize 支持
* pt、in、mm 这三个是比较少见的单位, 只可以选择其中的一个, 作为 AndroidAutoSize 的副单位, 与 dp、sp 一起被 AndroidAutoSize 支持
* 副单位是用于规避修改 {@link DisplayMetrics#density} 所造成的对于其他使用 dp 布局的系统控件或三方库控件的不良影响
* 您选择什么单位, 就在 layout 文件中用什么单位布局
*
* 两个主单位和一个副单位, 可以随时使用下面的方法关闭和重新开启对它们的支持
* 如果您想完全规避修改 {@link DisplayMetrics#density} 所造成的对于其他使用 dp 布局的系统控件或三方库控件的不良影响
* 那请调用 {@link #setSupportDP}、{@link #setSupportSP} 都设置为 {@code false}, 停止对两个主单位的支持 (如果开启 sp, 对其他三方库控件影响不大, 也可以不关闭对 sp 的支持)
* 并调用 {@link #setSupportSubunits} 从三个冷门单位中选择一个作为副单位 (三个单位的效果都是一样的, 按自己的喜好选择, 比如我就喜欢 mm, 翻译为中文是妹妹的意思)
* 然后在 layout 文件中只使用这个副单位进行布局, 这样就可以完全规避修改 {@link DisplayMetrics#density} 所造成的问题
* 因为 dp、sp 这两个单位在其他系统控件或三方库控件中都非常常见, 但三个冷门单位却非常少见
*
* Created by JessYan on 2018/8/28 10:21
* Contact me
* Follow me
* ================================================
*/
public class UnitsManager {
/**
* 设计图上的总宽度, 建议单位为 px, 当使用者想将旧项目从主单位过渡到副单位, 或从副单位过渡到主单位时使用
* 因为在使用主单位时, 建议在 AndroidManifest 中填写设计图的 dp 尺寸, 比如 360 * 640
* 而副单位有一个特性是可以直接在 AndroidManifest 中填写设计图的 px 尺寸, 比如 1080 * 1920
* 但在 AndroidManifest 中却只能填写一套设计图尺寸, 并且已经填写了主单位的设计图尺寸
* 所以当项目中同时存在副单位和主单位, 并且副单位的设计图尺寸与主单位的设计图尺寸不同时, 就需要在 {@link UnitsManager} 中保存副单位的设计图尺寸
*/
private float mDesignWidth;
/**
* 设计图上的总高度, 建议单位为 px, 当使用者想将旧项目从主单位过渡到副单位, 或从副单位过渡到主单位时使用
* 因为在使用主单位时, 建议在 AndroidManifest 中填写设计图的 dp 尺寸, 比如 360 * 640
* 而副单位有一个特性是可以直接在 AndroidManifest 中填写设计图的 px 尺寸, 比如 1080 * 1920
* 但在 AndroidManifest 中却只能填写一套设计图尺寸, 并且已经填写了主单位的设计图尺寸
* 所以当项目中同时存在副单位和主单位, 并且副单位的设计图尺寸与主单位的设计图尺寸不同时, 就需要在 {@link UnitsManager} 中保存副单位的设计图尺寸
*/
private float mDesignHeight;
/**
* 是否支持 dp 单位, 默认支持
*/
private boolean isSupportDP = true;
/**
* 是否支持 sp 单位, 默认支持
*/
private boolean isSupportSP = true;
/**
* 是否支持副单位, 以什么为副单位? 默认不支持
*/
private Subunits mSupportSubunits = Subunits.NONE;
/**
* 是否支持 ScreenSizeDp 修改, 默认不支持
*/
private boolean isSupportScreenSizeDP = false;
/**
* 设置设计图尺寸
*
* @param designWidth 设计图上的总宽度, 建议单位为 px
* @param designHeight 设计图上的总高度, 建议单位为 px
* @return {@link UnitsManager}
* @see #mDesignWidth 详情请查看这个字段的注释
* @see #mDesignHeight 详情请查看这个字段的注释
*/
public UnitsManager setDesignSize(float designWidth, float designHeight) {
setDesignWidth(designWidth);
setDesignHeight(designHeight);
return this;
}
/**
* 返回 {@link #mDesignWidth}
*
* @return {@link #mDesignWidth}
*/
public float getDesignWidth() {
return mDesignWidth;
}
/**
* 设置设计图上的总宽度, 建议单位为 px
*
* @param designWidth 设计图上的总宽度, 建议单位为 px
* @return {@link UnitsManager}
* @see #mDesignWidth 详情请查看这个字段的注释
*/
public UnitsManager setDesignWidth(float designWidth) {
Preconditions.checkArgument(designWidth > 0, "designWidth must be > 0");
mDesignWidth = designWidth;
return this;
}
/**
* 返回 {@link #mDesignHeight}
*
* @return {@link #mDesignHeight}
*/
public float getDesignHeight() {
return mDesignHeight;
}
/**
* 设置设计图上的总高度, 建议单位为 px
*
* @param designHeight 设计图上的总高度, 建议单位为 px
* @return {@link UnitsManager}
* @see #mDesignHeight 详情请查看这个字段的注释
*/
public UnitsManager setDesignHeight(float designHeight) {
Preconditions.checkArgument(designHeight > 0, "designHeight must be > 0");
mDesignHeight = designHeight;
return this;
}
/**
* 是否支持 dp 单位, 默认支持, 详情请看类文件的注释 {@link UnitsManager}
*
* @return {@code true} 为支持, {@code false} 为不支持
*/
public boolean isSupportDP() {
return isSupportDP;
}
/**
* 是否让 AndroidAutoSize 支持 dp 单位, 默认支持, 详情请看类文件的注释 {@link UnitsManager}
*
* @param supportDP {@code true} 为支持, {@code false} 为不支持
*/
public UnitsManager setSupportDP(boolean supportDP) {
isSupportDP = supportDP;
return this;
}
/**
* 是否支持 sp 单位, 默认支持, 详情请看类文件的注释 {@link UnitsManager}
*
* @return {@code true} 为支持, {@code false} 为不支持
*/
public boolean isSupportSP() {
return isSupportSP;
}
/**
* 是否让 AndroidAutoSize 支持 sp 单位, 默认支持, 详情请看类文件的注释 {@link UnitsManager}
*
* @param supportSP {@code true} 为支持, {@code false} 为不支持
*/
public UnitsManager setSupportSP(boolean supportSP) {
isSupportSP = supportSP;
return this;
}
/**
* AndroidAutoSize 以什么单位为副单位, 默认为 {@link Subunits#NONE}, 即不支持副单位, 详情请看类文件的注释 {@link UnitsManager}
*
* @return {@link Subunits}
*/
public Subunits getSupportSubunits() {
return mSupportSubunits;
}
/**
* 是否支持 ScreenSizeDp 修改, 默认不支持, 详情请看类文件的注释 {@link UnitsManager}
*
* @return {@code true} 为支持, {@code false} 为不支持
*/
public boolean isSupportScreenSizeDP() {
return isSupportScreenSizeDP;
}
/**
* 是否让 AndroidAutoSize 支持 ScreenSizeDp 修改, 默认不支持, 详情请看类文件的注释 {@link UnitsManager}
*
* @param supportScreenSizeDP {@code true} 为支持, {@code false} 为不支持
*/
public UnitsManager setSupportScreenSizeDP(boolean supportScreenSizeDP) {
isSupportScreenSizeDP = supportScreenSizeDP;
return this;
}
/**
* 让 AndroidAutoSize 以什么单位为副单位, 在 pt、in、mm 这三个冷门单位中选择一个即可, 三个效果都是一样的
* 按自己的喜好选择, 比如我就喜欢 mm, 翻译为中文是妹妹的意思
* 默认为 {@link Subunits#NONE}, 即不支持副单位, 详情请看类文件的注释 {@link UnitsManager}
*
* @param supportSubunits {@link Subunits}
*/
public UnitsManager setSupportSubunits(Subunits supportSubunits) {
mSupportSubunits = Preconditions.checkNotNull(supportSubunits,
"The supportSubunits can not be null, use Subunits.NONE instead");
return this;
}
}
================================================
FILE: autosize/src/main/java/me/jessyan/autosize/utils/AutoSizeLog.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize.utils;
import android.util.Log;
/**
* ================================================
* Created by JessYan on 2018/8/8 18:48
* Contact me
* Follow me
* ================================================
*/
public class AutoSizeLog {
private static final String TAG = "AndroidAutoSize";
private static boolean debug;
private AutoSizeLog() {
throw new IllegalStateException("you can't instantiate me!");
}
public static boolean isDebug() {
return debug;
}
public static void setDebug(boolean debug) {
AutoSizeLog.debug = debug;
}
public static void d(String message) {
if (debug) {
Log.d(TAG, message);
}
}
public static void w(String message) {
if (debug) {
Log.w(TAG, message);
}
}
public static void e(String message) {
if (debug) {
Log.e(TAG, message);
}
}
}
================================================
FILE: autosize/src/main/java/me/jessyan/autosize/utils/AutoSizeUtils.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize.utils;
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.TypedValue;
import android.app.Application;
import java.lang.reflect.InvocationTargetException;
/**
* ================================================
* AndroidAutoSize 常用工具类
*
* Created by JessYan on 2018/8/25 15:24
* Contact me
* Follow me
* ================================================
*/
public class AutoSizeUtils {
private AutoSizeUtils() {
throw new IllegalStateException("you can't instantiate me!");
}
public static int dp2px(Context context, float value) {
return (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, context.getResources().getDisplayMetrics()) + 0.5f);
}
public static int sp2px(Context context, float value) {
return (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, value, context.getResources().getDisplayMetrics()) + 0.5f);
}
public static int pt2px(Context context, float value) {
return (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PT, value, context.getResources().getDisplayMetrics()) + 0.5f);
}
public static int in2px(Context context, float value) {
return (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_IN, value, context.getResources().getDisplayMetrics()) + 0.5f);
}
public static int mm2px(Context context, float value) {
return (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, value, context.getResources().getDisplayMetrics()) + 0.5f);
}
public static Application getApplicationByReflect() {
try {
@SuppressLint("PrivateApi")
Class> activityThread = Class.forName("android.app.ActivityThread");
Object thread = activityThread.getMethod("currentActivityThread").invoke(null);
Object app = activityThread.getMethod("getApplication").invoke(thread);
if (app == null) {
throw new NullPointerException("you should init first");
}
return (Application) app;
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
throw new NullPointerException("you should init first");
}
}
================================================
FILE: autosize/src/main/java/me/jessyan/autosize/utils/Preconditions.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize.utils;
import android.os.Looper;
/**
* ================================================
* Created by JessYan on 26/09/2016 13:59
* Contact me
* Follow me
* ================================================
*/
public final class Preconditions {
private Preconditions() {
throw new IllegalStateException("you can't instantiate me!");
}
public static void checkArgument(boolean expression) {
if (!expression) {
throw new IllegalArgumentException();
}
}
public static void checkArgument(boolean expression, Object errorMessage) {
if (!expression) {
throw new IllegalArgumentException(String.valueOf(errorMessage));
}
}
public static void checkArgument(boolean expression, String errorMessageTemplate, Object... errorMessageArgs) {
if (!expression) {
throw new IllegalArgumentException(format(errorMessageTemplate, errorMessageArgs));
}
}
public static void checkState(boolean expression) {
if (!expression) {
throw new IllegalStateException();
}
}
public static void checkState(boolean expression, Object errorMessage) {
if (!expression) {
throw new IllegalStateException(String.valueOf(errorMessage));
}
}
public static void checkState(boolean expression, String errorMessageTemplate, Object... errorMessageArgs) {
if (!expression) {
throw new IllegalStateException(format(errorMessageTemplate, errorMessageArgs));
}
}
public static
* 本框架核心原理来自于 今日头条官方适配方案
*
* 本框架源码的注释都很详细, 欢迎阅读学习
*
* AndroidAutoSize 会在 APP 启动时自动完成初始化, 如果您想设置自定义参数可以在 {@link Application#onCreate()} 中设置
*
* Created by JessYan on 2018/8/9 17:05
* Contact me
* Follow me
* ================================================
*/
public class BaseApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
//当 App 中出现多进程, 并且您需要适配所有的进程, 就需要在 App 初始化时调用 initCompatMultiProcess()
//在 Demo 中跳转的三方库中的 DefaultErrorActivity 就是在另外一个进程中, 所以要想适配这个 Activity 就需要调用 initCompatMultiProcess()
AutoSize.initCompatMultiProcess(this);
//如果在某些特殊情况下出现 InitProvider 未能正常实例化, 导致 AndroidAutoSize 未能完成初始化
//可以主动调用 AutoSize.checkAndInit(this) 方法, 完成 AndroidAutoSize 的初始化后即可正常使用
// AutoSize.checkAndInit(this);
// 如何控制 AndroidAutoSize 的初始化,让 AndroidAutoSize 在某些设备上不自动启动?https://github.com/JessYanCoding/AndroidAutoSize/issues/249
/**
* 以下是 AndroidAutoSize 可以自定义的参数, {@link AutoSizeConfig} 的每个方法的注释都写的很详细
* 使用前请一定记得跳进源码,查看方法的注释, 下面的注释只是简单描述!!!
*/
AutoSizeConfig.getInstance()
//是否让框架支持自定义 Fragment 的适配参数, 由于这个需求是比较少见的, 所以须要使用者手动开启
//如果没有这个需求建议不开启
.setCustomFragment(true)
//是否屏蔽系统字体大小对 AndroidAutoSize 的影响, 如果为 true, App 内的字体的大小将不会跟随系统设置中字体大小的改变
//如果为 false, 则会跟随系统设置中字体大小的改变, 默认为 false
// .setExcludeFontScale(true)
//区别于系统字体大小的放大比例, AndroidAutoSize 允许 APP 内部可以独立于系统字体大小之外,独自拥有全局调节 APP 字体大小的能力
//当然, 在 APP 内您必须使用 sp 来作为字体的单位, 否则此功能无效, 不设置或将此值设为 0 则取消此功能
// .setPrivateFontScale(0.8f)
//屏幕适配监听器
.setOnAdaptListener(new onAdaptListener() {
@Override
public void onAdaptBefore(Object target, Activity activity) {
//使用以下代码, 可以解决横竖屏切换时的屏幕适配问题
//使用以下代码, 可支持 Android 的分屏或缩放模式, 但前提是在分屏或缩放模式下当用户改变您 App 的窗口大小时
//系统会重绘当前的页面, 经测试在某些机型, 某些情况下系统不会主动重绘当前页面, 所以这时您需要自行重绘当前页面
//ScreenUtils.getScreenSize(activity) 的参数一定要不要传 Application!!!
// AutoSizeConfig.getInstance().setScreenWidth(ScreenUtils.getScreenSize(activity)[0]);
// AutoSizeConfig.getInstance().setScreenHeight(ScreenUtils.getScreenSize(activity)[1]);
AutoSizeLog.d(String.format(Locale.ENGLISH, "%s onAdaptBefore!", target.getClass().getName()));
}
@Override
public void onAdaptAfter(Object target, Activity activity) {
AutoSizeLog.d(String.format(Locale.ENGLISH, "%s onAdaptAfter!", target.getClass().getName()));
}
})
//是否打印 AutoSize 的内部日志, 默认为 true, 如果您不想 AutoSize 打印日志, 则请设置为 false
// .setLog(false)
//是否使用设备的实际尺寸做适配, 默认为 false, 如果设置为 false, 在以屏幕高度为基准进行适配时
//AutoSize 会将屏幕总高度减去状态栏高度来做适配
//设置为 true 则使用设备的实际屏幕高度, 不会减去状态栏高度
//在全面屏或刘海屏幕设备中, 获取到的屏幕高度可能不包含状态栏高度, 所以在全面屏设备中不需要减去状态栏高度,所以可以 setUseDeviceSize(true)
// .setUseDeviceSize(true)
//是否全局按照宽度进行等比例适配, 默认为 true, 如果设置为 false, AutoSize 会全局按照高度进行适配
// .setBaseOnWidth(false)
//设置屏幕适配逻辑策略类, 一般不用设置, 使用框架默认的就好
// .setAutoAdaptStrategy(new AutoAdaptStrategy())
;
customAdaptForExternal();
}
/**
* 给外部的三方库 {@link Activity} 自定义适配参数, 因为三方库的 {@link Activity} 并不能通过实现
* {@link CustomAdapt} 接口的方式来提供自定义适配参数 (因为远程依赖改不了源码)
* 所以使用 {@link ExternalAdaptManager} 来替代实现接口的方式, 来提供自定义适配参数
*/
private void customAdaptForExternal() {
/**
* {@link ExternalAdaptManager} 是一个管理外部三方库的适配信息和状态的管理类, 详细介绍请看 {@link ExternalAdaptManager} 的类注释
*/
AutoSizeConfig.getInstance().getExternalAdaptManager()
//加入的 Activity 将会放弃屏幕适配, 一般用于三方库的 Activity, 详情请看方法注释
//如果不想放弃三方库页面的适配, 请用 addExternalAdaptInfoOfActivity 方法, 建议对三方库页面进行适配, 让自己的 App 更完美一点
// .addCancelAdaptOfActivity(DefaultErrorActivity.class)
//为指定的 Activity 提供自定义适配参数, AndroidAutoSize 将会按照提供的适配参数进行适配, 详情请看方法注释
//一般用于三方库的 Activity, 因为三方库的设计图尺寸可能和项目自身的设计图尺寸不一致, 所以要想完美适配三方库的页面
//就需要提供三方库的设计图尺寸, 以及适配的方向 (以宽为基准还是高为基准?)
//三方库页面的设计图尺寸可能无法获知, 所以如果想让三方库的适配效果达到最好, 只有靠不断的尝试
//由于 AndroidAutoSize 可以让布局在所有设备上都等比例缩放, 所以只要您在一个设备上测试出了一个最完美的设计图尺寸
//那这个三方库页面在其他设备上也会呈现出同样的适配效果, 等比例缩放, 所以也就完成了三方库页面的屏幕适配
//即使在不改三方库源码的情况下也可以完美适配三方库的页面, 这就是 AndroidAutoSize 的优势
//但前提是三方库页面的布局使用的是 dp 和 sp, 如果布局全部使用的 px, 那 AndroidAutoSize 也将无能为力
//经过测试 DefaultErrorActivity 的设计图宽度在 380dp - 400dp 显示效果都是比较舒服的
.addExternalAdaptInfoOfActivity(DefaultErrorActivity.class, new ExternalAdaptInfo(true, 400));
}
}
================================================
FILE: demo/src/main/java/me/jessyan/autosize/demo/CustomAdaptActivity.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize.demo;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import me.jessyan.autosize.internal.CustomAdapt;
/**
* ================================================
* 本框架核心原理来自于 今日头条官方适配方案
*
* {@link CustomAdaptActivity} 展示项目内部的 {@link Activity} 自定义适配参数的用法, 需要实现 {@link CustomAdapt}
* 现在 AndroidAutoSize 是全局以屏幕宽度为基准进行适配的, 并且全局的设计图尺寸为 360 * 640
* 这里就展示怎么让 {@link CustomAdaptActivity} 单个页面, 有别于全局设置, 以屏幕高度为基准进行适配, 并且更改设计图尺寸为 iPhone 的设计图尺寸
* 如果这个页面的设计图尺寸有别于其他页面, AndroidAutoSize 允许您改变单个页面的设计图尺寸, {@link #getSizeInDp()}
*
* Created by JessYan on 2018/8/11 11:31
* Contact me
* Follow me
* ================================================
*/
public class CustomAdaptActivity extends AppCompatActivity implements CustomAdapt {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_adapt);
}
/**
* 跳转到 {@link FragmentHost}, 展示项目内部的 {@link Fragment} 自定义适配参数的用法
*
* @param view {@link View}
*/
public void goCustomAdaptFragment(View view) {
startActivity(new Intent(getApplicationContext(), FragmentHost.class));
}
/**
* 是否按照宽度进行等比例适配 (为了保证在高宽比不同的屏幕上也能正常适配, 所以只能在宽度和高度之中选择一个作为基准进行适配)
*
* @return {@code true} 为按照宽度进行适配, {@code false} 为按照高度进行适配
*/
@Override
public boolean isBaseOnWidth() {
return false;
}
/**
* 这里使用 iPhone 的设计图, iPhone 的设计图尺寸为 750px * 1334px, 高换算成 dp 为 667 (1334px / 2 = 667dp)
*
* 返回设计图上的设计尺寸, 单位 dp
* {@link #getSizeInDp} 须配合 {@link #isBaseOnWidth()} 使用, 规则如下:
* 如果 {@link #isBaseOnWidth()} 返回 {@code true}, {@link #getSizeInDp} 则应该返回设计图的总宽度
* 如果 {@link #isBaseOnWidth()} 返回 {@code false}, {@link #getSizeInDp} 则应该返回设计图的总高度
* 如果您不需要自定义设计图上的设计尺寸, 想继续使用在 AndroidManifest 中填写的设计图尺寸, {@link #getSizeInDp} 则返回 {@code 0}
*
* @return 设计图上的设计尺寸, 单位 dp
*/
@Override
public float getSizeInDp() {
return 667;
}
}
================================================
FILE: demo/src/main/java/me/jessyan/autosize/demo/CustomFragment1.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize.demo;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import me.jessyan.autosize.AutoSize;
import me.jessyan.autosize.internal.CustomAdapt;
import me.jessyan.autosize.utils.AutoSizeUtils;
/**
* ================================================
* Created by JessYan on 2018/8/25 14:06
* Contact me
* Follow me
* ================================================
*/
public class CustomFragment1 extends Fragment implements CustomAdapt {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//由于某些原因, 屏幕旋转后 Fragment 的重建, 会导致框架对 Fragment 的自定义适配参数失去效果
//所以如果您的 Fragment 允许屏幕旋转, 则请在 onCreateView 手动调用一次 AutoSize.autoConvertDensity()
//如果您的 Fragment 不允许屏幕旋转, 则可以将下面调用 AutoSize.autoConvertDensity() 的代码删除掉
AutoSize.autoConvertDensity(getActivity(), 1080, true);
return createTextView(inflater, "Fragment-1\nView width = 360dp\nTotal width = 1080dp", 0xffff0000);
}
@Override
public boolean isBaseOnWidth() {
return true;
}
@Override
public float getSizeInDp() {
return 1080;
}
public static View createTextView(LayoutInflater inflater, String content, int backgroundColor) {
TextView view = new TextView(inflater.getContext());
ViewGroup.LayoutParams layoutParams =
new ViewGroup.LayoutParams((AutoSizeUtils.dp2px(inflater.getContext(), 360)),
ViewGroup.LayoutParams.MATCH_PARENT);
view.setLayoutParams(layoutParams);
view.setText(content);
view.setTextColor(0xffffffff);
view.setGravity(Gravity.CENTER);
view.setTextSize(30);
view.setBackgroundColor(backgroundColor);
return view;
}
}
================================================
FILE: demo/src/main/java/me/jessyan/autosize/demo/CustomFragment2.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize.demo;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import me.jessyan.autosize.AutoSize;
import me.jessyan.autosize.internal.CustomAdapt;
/**
* ================================================
* Created by JessYan on 2018/8/25 14:06
* Contact me
* Follow me
* ================================================
*/
public class CustomFragment2 extends Fragment implements CustomAdapt{
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//由于某些原因, 屏幕旋转后 Fragment 的重建, 会导致框架对 Fragment 的自定义适配参数失去效果
//所以如果您的 Fragment 允许屏幕旋转, 则请在 onCreateView 手动调用一次 AutoSize.autoConvertDensity()
//如果您的 Fragment 不允许屏幕旋转, 则可以将下面调用 AutoSize.autoConvertDensity() 的代码删除掉
AutoSize.autoConvertDensity(getActivity(), 720, true);
return CustomFragment1.createTextView(inflater, "Fragment-2\nView width = 360dp\nTotal width = 720dp", 0xff00ff00);
}
@Override
public boolean isBaseOnWidth() {
return true;
}
@Override
public float getSizeInDp() {
return 720;
}
}
================================================
FILE: demo/src/main/java/me/jessyan/autosize/demo/CustomFragment3.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize.demo;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import me.jessyan.autosize.AutoSize;
import me.jessyan.autosize.internal.CustomAdapt;
/**
* ================================================
* Created by JessYan on 2018/8/25 14:06
* Contact me
* Follow me
* ================================================
*/
public class CustomFragment3 extends Fragment implements CustomAdapt{
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//由于某些原因, 屏幕旋转后 Fragment 的重建, 会导致框架对 Fragment 的自定义适配参数失去效果
//所以如果您的 Fragment 允许屏幕旋转, 则请在 onCreateView 手动调用一次 AutoSize.autoConvertDensity()
//如果您的 Fragment 不允许屏幕旋转, 则可以将下面调用 AutoSize.autoConvertDensity() 的代码删除掉
AutoSize.autoConvertDensity(getActivity(), 360, true);
return CustomFragment1.createTextView(inflater, "Fragment-3\nView width = 360dp\nTotal width = 360dp", 0xff0000ff);
}
@Override
public boolean isBaseOnWidth() {
return true;
}
@Override
public float getSizeInDp() {
return 360;
}
}
================================================
FILE: demo/src/main/java/me/jessyan/autosize/demo/FragmentHost.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize.demo;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import me.jessyan.autosize.internal.CustomAdapt;
/**
* ================================================
* Created by JessYan on 2018/8/25 14:39
* Contact me
* Follow me
* ================================================
*/
public class FragmentHost extends AppCompatActivity implements CustomAdapt {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_host);
if (getSupportFragmentManager().findFragmentById(R.id.container1) == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container1, new CustomFragment1()).commit();
}
if (getSupportFragmentManager().findFragmentById(R.id.container2) == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container2, new CustomFragment2()).commit();
}
if (getSupportFragmentManager().findFragmentById(R.id.container3) == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container3, new CustomFragment3()).commit();
}
}
@Override
public boolean isBaseOnWidth() {
return true;
}
@Override
public float getSizeInDp() {
return 720;
}
}
================================================
FILE: demo/src/main/java/me/jessyan/autosize/demo/MainActivity.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize.demo;
import android.app.Activity;
import android.app.Dialog;
import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;
import cat.ereza.customactivityoncrash.activity.DefaultErrorActivity;
import cat.ereza.customactivityoncrash.config.CaocConfig;
import me.jessyan.autosize.AutoSizeConfig;
import me.jessyan.autosize.internal.CustomAdapt;
/**
* ================================================
* 本框架核心原理来自于 今日头条官方适配方案
* 此方案不光可以适配 {@link Activity}, 这个 {@link Activity} 下的所有 {@link Fragment}、{@link Dialog}、{@link View} 都会自动适配
*
* {@link MainActivity} 是以屏幕宽度为基准进行适配的, 并且使用的是在 AndroidManifest 中填写的全局设计图尺寸 360 * 640
* 不懂什么叫基准的话, 请看 {@link AutoSizeConfig#isBaseOnWidth}) 的注释, AndroidAutoSize 默认全局以屏幕宽度为基准进行适配
* 如果想更改为全局以屏幕高度为基准进行适配, 请在 {@link BaseApplication} 中按注释中更改, 为什么强调全局?
* 因为 AndroidAutoSize 允许每个 {@link Activity} 可以自定义适配参数, 自定义适配参数通过实现 {@link CustomAdapt}
* 如果不自定义适配参数就会使用全局的适配参数, 全局适配参数在 {@link BaseApplication} 中按注释设置
*
* Created by JessYan on 2018/8/9 17:05
* Contact me
* Follow me
* ================================================
*/
//实现 CancelAdapt 即可取消当前 Activity 的屏幕适配, 并且这个 Activity 下的所有 Fragment 和 View 都会被取消适配
//public class MainActivity extends AppCompatActivity implements CancelAdapt {
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* 需要注意的是暂停 AndroidAutoSize 后, AndroidAutoSize 只是停止了对后续还没有启动的 {@link Activity} 进行适配的工作
* 但对已经启动且已经适配的 {@link Activity} 不会有任何影响
*
* @param view {@link View}
*/
public void stop(View view) {
Toast.makeText(getApplicationContext(), "AndroidAutoSize stops working!", Toast.LENGTH_SHORT).show();
AutoSizeConfig.getInstance().stop(this);
}
/**
* 需要注意的是重新启动 AndroidAutoSize 后, AndroidAutoSize 只是重新开始了对后续还没有启动的 {@link Activity} 进行适配的工作
* 但对已经启动且在 stop 期间未适配的 {@link Activity} 不会有任何影响
*
* @param view {@link View}
*/
public void restart(View view) {
Toast.makeText(getApplicationContext(), "AndroidAutoSize continues to work", Toast.LENGTH_SHORT).show();
AutoSizeConfig.getInstance().restart();
}
/**
* 跳转到 {@link CustomAdaptActivity}, 展示项目内部的 {@link Activity} 自定义适配参数的用法
*
* @param view {@link View}
*/
public void goCustomAdaptActivity(View view) {
startActivity(new Intent(getApplicationContext(), CustomAdaptActivity.class));
}
/**
* 跳转到三方库的 {@link Activity}, 展示项目外部某些三方库的 {@link Activity} 自定义适配参数的用法
* 跳转前要先在 {@link BaseApplication#customAdaptForExternal()} 中给外部的三方库 {@link Activity} 自定义适配参数
*
* @param view {@link View}
*/
public void goThirdLibraryActivity(View view) {
//这里就是随便找个三方库的 Activity, 测试下适配三方库页面的功能是否可用
//以下代码就是为了启动这个三方库的 Activity, 不必在意
Intent intent = new Intent(getApplicationContext(), DefaultErrorActivity.class);
Bundle extras = new Bundle();
extras.putSerializable("cat.ereza.customactivityoncrash.EXTRA_CONFIG", CaocConfig.Builder.create().get());
intent.putExtras(extras);
startActivity(intent);
}
}
================================================
FILE: demo/src/main/res/drawable/ic_launcher_background.xml
================================================
* 本框架核心原理来自于 今日头条官方适配方案
*
* 本框架源码的注释都很详细, 欢迎阅读学习
*
* AndroidAutoSize 会在 APP 启动时自动完成初始化, 如果您想设置自定义参数可以在 {@link Application#onCreate()} 中设置
*
* Created by JessYan on 2018/8/9 17:05
* Contact me
* Follow me
* ================================================
*/
public class BaseApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
//当 App 中出现多进程, 并且您需要适配所有的进程, 就需要在 App 初始化时调用 initCompatMultiProcess()
AutoSize.initCompatMultiProcess(this);
//如果在某些特殊情况下出现 InitProvider 未能正常实例化, 导致 AndroidAutoSize 未能完成初始化
//可以主动调用 AutoSize.checkAndInit(this) 方法, 完成 AndroidAutoSize 的初始化后即可正常使用
// AutoSize.checkAndInit(this);
// 如何控制 AndroidAutoSize 的初始化,让 AndroidAutoSize 在某些设备上不自动启动?https://github.com/JessYanCoding/AndroidAutoSize/issues/249
/**
* 以下是 AndroidAutoSize 可以自定义的参数, {@link AutoSizeConfig} 的每个方法的注释都写的很详细
* 使用前请一定记得跳进源码,查看方法的注释, 下面的注释只是简单描述!!!
*/
AutoSizeConfig.getInstance()
//是否让框架支持自定义 Fragment 的适配参数, 由于这个需求是比较少见的, 所以须要使用者手动开启
//如果没有这个需求建议不开启
.setCustomFragment(true)
//是否屏蔽系统字体大小对 AndroidAutoSize 的影响, 如果为 true, App 内的字体的大小将不会跟随系统设置中字体大小的改变
//如果为 false, 则会跟随系统设置中字体大小的改变, 默认为 false
// .setExcludeFontScale(true)
//区别于系统字体大小的放大比例, AndroidAutoSize 允许 APP 内部可以独立于系统字体大小之外,独自拥有全局调节 APP 字体大小的能力
//当然, 在 APP 内您必须使用 sp 来作为字体的单位, 否则此功能无效, 不设置或将此值设为 0 则取消此功能
// .setPrivateFontScale(0.8f)
//屏幕适配监听器
.setOnAdaptListener(new onAdaptListener() {
@Override
public void onAdaptBefore(Object target, Activity activity) {
//使用以下代码, 可以解决横竖屏切换时的屏幕适配问题
//使用以下代码, 可支持 Android 的分屏或缩放模式, 但前提是在分屏或缩放模式下当用户改变您 App 的窗口大小时
//系统会重绘当前的页面, 经测试在某些机型, 某些情况下系统不会重绘当前页面, ScreenUtils.getScreenSize(activity) 的参数一定要不要传 Application!!!
// AutoSizeConfig.getInstance().setScreenWidth(ScreenUtils.getScreenSize(activity)[0]);
// AutoSizeConfig.getInstance().setScreenHeight(ScreenUtils.getScreenSize(activity)[1]);
AutoSizeLog.d(String.format(Locale.ENGLISH, "%s onAdaptBefore!", target.getClass().getName()));
}
@Override
public void onAdaptAfter(Object target, Activity activity) {
AutoSizeLog.d(String.format(Locale.ENGLISH, "%s onAdaptAfter!", target.getClass().getName()));
}
})
//是否打印 AutoSize 的内部日志, 默认为 true, 如果您不想 AutoSize 打印日志, 则请设置为 false
// .setLog(false)
//是否使用设备的实际尺寸做适配, 默认为 false, 如果设置为 false, 在以屏幕高度为基准进行适配时
//AutoSize 会将屏幕总高度减去状态栏高度来做适配
//设置为 true 则使用设备的实际屏幕高度, 不会减去状态栏高度
//在全面屏或刘海屏幕设备中, 获取到的屏幕高度可能不包含状态栏高度, 所以在全面屏设备中不需要减去状态栏高度,所以可以 setUseDeviceSize(true)
// .setUseDeviceSize(true)
//是否全局按照宽度进行等比例适配, 默认为 true, 如果设置为 false, AutoSize 会全局按照高度进行适配
// .setBaseOnWidth(false)
//设置屏幕适配逻辑策略类, 一般不用设置, 使用框架默认的就好
// .setAutoAdaptStrategy(new AutoAdaptStrategy())
;
}
}
================================================
FILE: demo-androidx/src/main/java/me/jessyan/autosize/demo/androidx/CustomAdaptActivity.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize.demo.androidx;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import me.jessyan.autosize.internal.CustomAdapt;
/**
* ================================================
* 本框架核心原理来自于 今日头条官方适配方案
*
* {@link CustomAdaptActivity} 展示项目内部的 {@link Activity} 自定义适配参数的用法, 需要实现 {@link CustomAdapt}
* 现在 AndroidAutoSize 是全局以屏幕宽度为基准进行适配的, 并且全局的设计图尺寸为 360 * 640
* 这里就展示怎么让 {@link CustomAdaptActivity} 单个页面, 有别于全局设置, 以屏幕高度为基准进行适配, 并且更改设计图尺寸为 iPhone 的设计图尺寸
* 如果这个页面的设计图尺寸有别于其他页面, AndroidAutoSize 允许您改变单个页面的设计图尺寸, {@link #getSizeInDp()}
*
* Created by JessYan on 2018/8/11 11:31
* Contact me
* Follow me
* ================================================
*/
public class CustomAdaptActivity extends AppCompatActivity implements CustomAdapt {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_adapt);
}
/**
* 跳转到 {@link FragmentHost}, 展示项目内部的 {@link Fragment} 自定义适配参数的用法
*
* @param view {@link View}
*/
public void goCustomAdaptFragment(View view) {
startActivity(new Intent(getApplicationContext(), FragmentHost.class));
}
/**
* 是否按照宽度进行等比例适配 (为了保证在高宽比不同的屏幕上也能正常适配, 所以只能在宽度和高度之中选择一个作为基准进行适配)
*
* @return {@code true} 为按照宽度进行适配, {@code false} 为按照高度进行适配
*/
@Override
public boolean isBaseOnWidth() {
return false;
}
/**
* 这里使用 iPhone 的设计图, iPhone 的设计图尺寸为 750px * 1334px, 高换算成 dp 为 667 (1334px / 2 = 667dp)
*
* 返回设计图上的设计尺寸, 单位 dp
* {@link #getSizeInDp} 须配合 {@link #isBaseOnWidth()} 使用, 规则如下:
* 如果 {@link #isBaseOnWidth()} 返回 {@code true}, {@link #getSizeInDp} 则应该返回设计图的总宽度
* 如果 {@link #isBaseOnWidth()} 返回 {@code false}, {@link #getSizeInDp} 则应该返回设计图的总高度
* 如果您不需要自定义设计图上的设计尺寸, 想继续使用在 AndroidManifest 中填写的设计图尺寸, {@link #getSizeInDp} 则返回 {@code 0}
*
* @return 设计图上的设计尺寸, 单位 dp
*/
@Override
public float getSizeInDp() {
return 667;
}
}
================================================
FILE: demo-androidx/src/main/java/me/jessyan/autosize/demo/androidx/CustomFragment1.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize.demo.androidx;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import me.jessyan.autosize.AutoSize;
import me.jessyan.autosize.internal.CustomAdapt;
import me.jessyan.autosize.utils.AutoSizeUtils;
/**
* ================================================
* Created by JessYan on 2018/8/25 14:06
* Contact me
* Follow me
* ================================================
*/
public class CustomFragment1 extends Fragment implements CustomAdapt {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//由于某些原因, 屏幕旋转后 Fragment 的重建, 会导致框架对 Fragment 的自定义适配参数失去效果
//所以如果您的 Fragment 允许屏幕旋转, 则请在 onCreateView 手动调用一次 AutoSize.autoConvertDensity()
//如果您的 Fragment 不允许屏幕旋转, 则可以将下面调用 AutoSize.autoConvertDensity() 的代码删除掉
AutoSize.autoConvertDensity(getActivity(), 1080, true);
return createTextView(inflater, "Fragment-1\nView width = 360dp\nTotal width = 1080dp", 0xffff0000);
}
@Override
public boolean isBaseOnWidth() {
return true;
}
@Override
public float getSizeInDp() {
return 1080;
}
public static View createTextView(LayoutInflater inflater, String content, int backgroundColor) {
TextView view = new TextView(inflater.getContext());
ViewGroup.LayoutParams layoutParams =
new ViewGroup.LayoutParams((AutoSizeUtils.dp2px(inflater.getContext(), 360)),
ViewGroup.LayoutParams.MATCH_PARENT);
view.setLayoutParams(layoutParams);
view.setText(content);
view.setTextColor(0xffffffff);
view.setGravity(Gravity.CENTER);
view.setTextSize(30);
view.setBackgroundColor(backgroundColor);
return view;
}
}
================================================
FILE: demo-androidx/src/main/java/me/jessyan/autosize/demo/androidx/CustomFragment2.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize.demo.androidx;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import me.jessyan.autosize.AutoSize;
import me.jessyan.autosize.internal.CustomAdapt;
/**
* ================================================
* Created by JessYan on 2018/8/25 14:06
* Contact me
* Follow me
* ================================================
*/
public class CustomFragment2 extends Fragment implements CustomAdapt{
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//由于某些原因, 屏幕旋转后 Fragment 的重建, 会导致框架对 Fragment 的自定义适配参数失去效果
//所以如果您的 Fragment 允许屏幕旋转, 则请在 onCreateView 手动调用一次 AutoSize.autoConvertDensity()
//如果您的 Fragment 不允许屏幕旋转, 则可以将下面调用 AutoSize.autoConvertDensity() 的代码删除掉
AutoSize.autoConvertDensity(getActivity(), 720, true);
return CustomFragment1.createTextView(inflater, "Fragment-2\nView width = 360dp\nTotal width = 720dp", 0xff00ff00);
}
@Override
public boolean isBaseOnWidth() {
return true;
}
@Override
public float getSizeInDp() {
return 720;
}
}
================================================
FILE: demo-androidx/src/main/java/me/jessyan/autosize/demo/androidx/CustomFragment3.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize.demo.androidx;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import me.jessyan.autosize.AutoSize;
import me.jessyan.autosize.internal.CustomAdapt;
/**
* ================================================
* Created by JessYan on 2018/8/25 14:06
* Contact me
* Follow me
* ================================================
*/
public class CustomFragment3 extends Fragment implements CustomAdapt{
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//由于某些原因, 屏幕旋转后 Fragment 的重建, 会导致框架对 Fragment 的自定义适配参数失去效果
//所以如果您的 Fragment 允许屏幕旋转, 则请在 onCreateView 手动调用一次 AutoSize.autoConvertDensity()
//如果您的 Fragment 不允许屏幕旋转, 则可以将下面调用 AutoSize.autoConvertDensity() 的代码删除掉
AutoSize.autoConvertDensity(getActivity(), 360, true);
return CustomFragment1.createTextView(inflater, "Fragment-3\nView width = 360dp\nTotal width = 360dp", 0xff0000ff);
}
@Override
public boolean isBaseOnWidth() {
return true;
}
@Override
public float getSizeInDp() {
return 360;
}
}
================================================
FILE: demo-androidx/src/main/java/me/jessyan/autosize/demo/androidx/FragmentHost.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize.demo.androidx;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import me.jessyan.autosize.internal.CustomAdapt;
/**
* ================================================
* Created by JessYan on 2018/8/25 14:39
* Contact me
* Follow me
* ================================================
*/
public class FragmentHost extends AppCompatActivity implements CustomAdapt {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_host);
if (getSupportFragmentManager().findFragmentById(R.id.container1) == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container1, new CustomFragment1()).commit();
}
if (getSupportFragmentManager().findFragmentById(R.id.container2) == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container2, new CustomFragment2()).commit();
}
if (getSupportFragmentManager().findFragmentById(R.id.container3) == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container3, new CustomFragment3()).commit();
}
}
@Override
public boolean isBaseOnWidth() {
return true;
}
@Override
public float getSizeInDp() {
return 720;
}
}
================================================
FILE: demo-androidx/src/main/java/me/jessyan/autosize/demo/androidx/MainActivity.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize.demo.androidx;
import android.app.Activity;
import android.app.Dialog;
import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import me.jessyan.autosize.AutoSizeConfig;
import me.jessyan.autosize.internal.CustomAdapt;
/**
* ================================================
* 本框架核心原理来自于 今日头条官方适配方案
* 此方案不光可以适配 {@link Activity}, 这个 {@link Activity} 下的所有 {@link Fragment}、{@link Dialog}、{@link View} 都会自动适配
*
* {@link MainActivity} 是以屏幕宽度为基准进行适配的, 并且使用的是在 AndroidManifest 中填写的全局设计图尺寸 360 * 640
* 不懂什么叫基准的话, 请看 {@link AutoSizeConfig#isBaseOnWidth}) 的注释, AndroidAutoSize 默认全局以屏幕宽度为基准进行适配
* 如果想更改为全局以屏幕高度为基准进行适配, 请在 {@link BaseApplication} 中按注释中更改, 为什么强调全局?
* 因为 AndroidAutoSize 允许每个 {@link Activity} 可以自定义适配参数, 自定义适配参数通过实现 {@link CustomAdapt}
* 如果不自定义适配参数就会使用全局的适配参数, 全局适配参数在 {@link BaseApplication} 中按注释设置
*
* Created by JessYan on 2018/8/9 17:05
* Contact me
* Follow me
* ================================================
*/
//实现 CancelAdapt 即可取消当前 Activity 的屏幕适配, 并且这个 Activity 下的所有 Fragment 和 View 都会被取消适配
//public class MainActivity extends AppCompatActivity implements CancelAdapt {
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* 需要注意的是暂停 AndroidAutoSize 后, AndroidAutoSize 只是停止了对后续还没有启动的 {@link Activity} 进行适配的工作
* 但对已经启动且已经适配的 {@link Activity} 不会有任何影响
*
* @param view {@link View}
*/
public void stop(View view) {
Toast.makeText(getApplicationContext(), "AndroidAutoSize stops working!", Toast.LENGTH_SHORT).show();
AutoSizeConfig.getInstance().stop(this);
}
/**
* 需要注意的是重新启动 AndroidAutoSize 后, AndroidAutoSize 只是重新开始了对后续还没有启动的 {@link Activity} 进行适配的工作
* 但对已经启动且在 stop 期间未适配的 {@link Activity} 不会有任何影响
*
* @param view {@link View}
*/
public void restart(View view) {
Toast.makeText(getApplicationContext(), "AndroidAutoSize continues to work", Toast.LENGTH_SHORT).show();
AutoSizeConfig.getInstance().restart();
}
/**
* 跳转到 {@link CustomAdaptActivity}, 展示项目内部的 {@link Activity} 自定义适配参数的用法
*
* @param view {@link View}
*/
public void goCustomAdaptActivity(View view) {
startActivity(new Intent(getApplicationContext(), CustomAdaptActivity.class));
}
}
================================================
FILE: demo-androidx/src/main/res/drawable/ic_launcher_background.xml
================================================
* 本框架源码的注释都很详细, 欢迎阅读学习
*
* AndroidAutoSize 会在 APP 启动时自动完成初始化, 如果您想设置自定义参数可以在 {@link Application#onCreate()} 中设置
*
* Created by JessYan on 2018/8/9 17:05
* Contact me
* Follow me
* ================================================
*/
public class BaseApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
//对单位的自定义配置, 请在 App 启动时完成
configUnits();
}
/**
* 注意!!! 布局时的实时预览在开发阶段是一个很重要的环节, 很多情况下 Android Studio 提供的默认预览设备并不能完全展示我们的设计图
* 所以我们就需要自己创建模拟设备, 以下链接是给大家的福利, 按照链接中的操作可以让预览效果和设计图完全一致!
* @see dp、pt、in、mm 这四种单位的模拟设备创建方法
*
* v0.9.0 以后, AndroidAutoSize 强势升级, 将这个方案做到极致, 现在支持5种单位 (dp、sp、pt、in、mm)
* {@link UnitsManager} 可以让使用者随意配置自己想使用的单位类型
* 其中 dp、sp 这两个是比较常见的单位, 作为 AndroidAutoSize 的主单位, 默认被 AndroidAutoSize 支持
* pt、in、mm 这三个是比较少见的单位, 只可以选择其中的一个, 作为 AndroidAutoSize 的副单位, 与 dp、sp 一起被 AndroidAutoSize 支持
* 副单位是用于规避修改 {@link DisplayMetrics#density} 所造成的对于其他使用 dp 布局的系统控件或三方库控件的不良影响
* 您选择什么单位, 就在 layout 文件中用什么单位布局
*
* 两个主单位和一个副单位, 可以随时使用 {@link UnitsManager} 的方法关闭和重新开启对它们的支持
* 如果您想完全规避修改 {@link DisplayMetrics#density} 所造成的对于其他使用 dp 布局的系统控件或三方库控件的不良影响
* 那请调用 {@link UnitsManager#setSupportDP}、{@link UnitsManager#setSupportSP} 都设置为 {@code false}
* 停止对两个主单位的支持 (如果开启 sp, 对其他三方库控件影响不大, 也可以不关闭对 sp 的支持)
* 并调用 {@link UnitsManager#setSupportSubunits} 从三个冷门单位中选择一个作为副单位
* 三个单位的效果都是一样的, 按自己的喜好选择, 比如我就喜欢 mm, 翻译为中文是妹妹的意思
* 然后在 layout 文件中只使用这个副单位进行布局, 这样就可以完全规避修改 {@link DisplayMetrics#density} 所造成的不良影响
* 因为 dp、sp 这两个单位在其他系统控件或三方库控件中都非常常见, 但三个冷门单位却非常少见
*/
private void configUnits() {
//AndroidAutoSize 默认开启对 dp 的支持, 调用 UnitsManager.setSupportDP(false); 可以关闭对 dp 的支持
//主单位 dp 和 副单位可以同时开启的原因是, 对于旧项目中已经使用了 dp 进行布局的页面的兼容
//让开发者的旧项目可以渐进式的从 dp 切换到副单位, 即新页面用副单位进行布局, 然后抽时间逐渐的将旧页面的布局单位从 dp 改为副单位
//最后将 dp 全部改为副单位后, 再使用 UnitsManager.setSupportDP(false); 将 dp 的支持关闭, 彻底隔离修改 density 所造成的不良影响
//如果项目完全使用副单位, 则可以直接以像素为单位填写 AndroidManifest 中需要填写的设计图尺寸, 不需再把像素转化为 dp
AutoSizeConfig.getInstance().getUnitsManager()
.setSupportDP(false)
//当使用者想将旧项目从主单位过渡到副单位, 或从副单位过渡到主单位时
//因为在使用主单位时, 建议在 AndroidManifest 中填写设计图的 dp 尺寸, 比如 360 * 640
//而副单位有一个特性是可以直接在 AndroidManifest 中填写设计图的 px 尺寸, 比如 1080 * 1920
//但在 AndroidManifest 中却只能填写一套设计图尺寸, 并且已经填写了主单位的设计图尺寸
//所以当项目中同时存在副单位和主单位, 并且副单位的设计图尺寸与主单位的设计图尺寸不同时, 可以通过 UnitsManager#setDesignSize() 方法配置
//如果副单位的设计图尺寸与主单位的设计图尺寸相同, 则不需要调用 UnitsManager#setDesignSize(), 框架会自动使用 AndroidManifest 中填写的设计图尺寸
// .setDesignSize(2160, 3840)
//AndroidAutoSize 默认开启对 sp 的支持, 调用 UnitsManager.setSupportSP(false); 可以关闭对 sp 的支持
//如果关闭对 sp 的支持, 在布局时就应该使用副单位填写字体的尺寸
//如果开启 sp, 对其他三方库控件影响不大, 也可以不关闭对 sp 的支持, 这里我就继续开启 sp, 请自行斟酌自己的项目是否需要关闭对 sp 的支持
// .setSupportSP(false)
//AndroidAutoSize 默认不支持副单位, 调用 UnitsManager#setSupportSubunits() 可选择一个自己心仪的副单位, 并开启对副单位的支持
//只能在 pt、in、mm 这三个冷门单位中选择一个作为副单位, 三个单位的适配效果其实都是一样的, 您觉的哪个单位看起顺眼就用哪个
//您选择什么单位就在 layout 文件中用什么单位进行布局, 我选择用 mm 为单位进行布局, 因为 mm 翻译为中文是妹妹的意思
//如果大家生活中没有妹妹, 那我们就让项目中最不缺的就是妹妹!
.setSupportSubunits(Subunits.MM);
}
}
================================================
FILE: demo-subunits/src/main/java/me/jessyan/autosize/demo/subunits/CustomAdaptActivity.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize.demo.subunits;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import me.jessyan.autosize.internal.CustomAdapt;
/**
* ================================================
* 本框架核心原理来自于 今日头条官方适配方案
*
* Created by JessYan on 2018/8/11 11:31
* Contact me
* Follow me
* ================================================
*/
public class CustomAdaptActivity extends AppCompatActivity implements CustomAdapt {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_adapt);
}
/**
* 是否按照宽度进行等比例适配 (为了保证在高宽比不同的屏幕上也能正常适配, 所以只能在宽度和高度之中选择一个作为基准进行适配)
*
* @return {@code true} 为按照宽度进行适配, {@code false} 为按照高度进行适配
*/
@Override
public boolean isBaseOnWidth() {
return false;
}
/**
* 这里使用 iPhone 的设计图, iPhone 的设计图尺寸为 750px * 1334px, 因为这个页面使用副单位进行布局
* 所以可以直接以像素作为单位返回设计图的尺寸
*
* 返回设计图上的设计尺寸
* {@link #getSizeInDp} 须配合 {@link #isBaseOnWidth()} 使用, 规则如下:
* 如果 {@link #isBaseOnWidth()} 返回 {@code true}, {@link #getSizeInDp} 则应该返回设计图的总宽度
* 如果 {@link #isBaseOnWidth()} 返回 {@code false}, {@link #getSizeInDp} 则应该返回设计图的总高度
* 如果您不需要自定义设计图上的设计尺寸, 想继续使用在 AndroidManifest 中填写的设计图尺寸, {@link #getSizeInDp} 则返回 {@code 0}
*
* @return 设计图上的设计尺寸
*/
@Override
public float getSizeInDp() {
return 1334;
}
}
================================================
FILE: demo-subunits/src/main/java/me/jessyan/autosize/demo/subunits/MainActivity.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize.demo.subunits;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
/**
* ================================================
* 本框架核心原理来自于 今日头条官方适配方案
*
* Created by JessYan on 2018/8/9 17:05
* Contact me
* Follow me
* ================================================
*/
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* 跳转到 {@link CustomAdaptActivity}, 展示项目内部的 {@link Activity} 自定义适配参数的用法
*
* @param view {@link View}
*/
public void goCustomAdaptActivity(View view) {
startActivity(new Intent(getApplicationContext(), CustomAdaptActivity.class));
}
}
================================================
FILE: demo-subunits/src/main/res/drawable/ic_launcher_background.xml
================================================
*
*
* @param context {@link Context}
*/
private void getMetaData(final Context context) {
new Thread(new Runnable() {
@Override
public void run() {
PackageManager packageManager = context.getPackageManager();
ApplicationInfo applicationInfo;
try {
applicationInfo = packageManager.getApplicationInfo(context
.getPackageName(), PackageManager.GET_META_DATA);
if (applicationInfo != null && applicationInfo.metaData != null) {
if (applicationInfo.metaData.containsKey(KEY_DESIGN_WIDTH_IN_DP)) {
mDesignWidthInDp = (int) applicationInfo.metaData.get(KEY_DESIGN_WIDTH_IN_DP);
}
if (applicationInfo.metaData.containsKey(KEY_DESIGN_HEIGHT_IN_DP)) {
mDesignHeightInDp = (int) applicationInfo.metaData.get(KEY_DESIGN_HEIGHT_IN_DP);
}
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
}).start();
}
}
================================================
FILE: autosize/src/main/java/me/jessyan/autosize/DefaultAutoAdaptStrategy.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize;
import android.app.Activity;
import android.app.Application;
import java.util.Locale;
import me.jessyan.autosize.external.ExternalAdaptInfo;
import me.jessyan.autosize.internal.CancelAdapt;
import me.jessyan.autosize.internal.CustomAdapt;
import me.jessyan.autosize.utils.AutoSizeLog;
/**
* ================================================
* 屏幕适配逻辑策略默认实现类, 可通过 {@link AutoSizeConfig#init(Application, boolean, AutoAdaptStrategy)}
* 和 {@link AutoSizeConfig#setAutoAdaptStrategy(AutoAdaptStrategy)} 切换策略
*
* @see AutoAdaptStrategy
* Created by JessYan on 2018/8/9 15:57
* Contact me
* Follow me
* ================================================
*/
public class DefaultAutoAdaptStrategy implements AutoAdaptStrategy {
@Override
public void applyAdapt(Object target, Activity activity) {
//检查是否开启了外部三方库的适配模式, 只要不主动调用 ExternalAdaptManager 的方法, 下面的代码就不会执行
if (AutoSizeConfig.getInstance().getExternalAdaptManager().isRun()) {
if (AutoSizeConfig.getInstance().getExternalAdaptManager().isCancelAdapt(target.getClass())) {
AutoSizeLog.w(String.format(Locale.ENGLISH, "%s canceled the adaptation!", target.getClass().getName()));
AutoSize.cancelAdapt(activity);
return;
} else {
ExternalAdaptInfo info = AutoSizeConfig.getInstance().getExternalAdaptManager()
.getExternalAdaptInfoOfActivity(target.getClass());
if (info != null) {
AutoSizeLog.d(String.format(Locale.ENGLISH, "%s used %s for adaptation!", target.getClass().getName(), ExternalAdaptInfo.class.getName()));
AutoSize.autoConvertDensityOfExternalAdaptInfo(activity, info);
return;
}
}
}
//如果 target 实现 CancelAdapt 接口表示放弃适配, 所有的适配效果都将失效
if (target instanceof CancelAdapt) {
AutoSizeLog.w(String.format(Locale.ENGLISH, "%s canceled the adaptation!", target.getClass().getName()));
AutoSize.cancelAdapt(activity);
return;
}
//如果 target 实现 CustomAdapt 接口表示该 target 想自定义一些用于适配的参数, 从而改变最终的适配效果
if (target instanceof CustomAdapt) {
AutoSizeLog.d(String.format(Locale.ENGLISH, "%s implemented by %s!", target.getClass().getName(), CustomAdapt.class.getName()));
AutoSize.autoConvertDensityOfCustomAdapt(activity, (CustomAdapt) target);
} else {
AutoSizeLog.d(String.format(Locale.ENGLISH, "%s used the global configuration.", target.getClass().getName()));
AutoSize.autoConvertDensityOfGlobal(activity);
}
}
}
================================================
FILE: autosize/src/main/java/me/jessyan/autosize/DisplayMetricsInfo.java
================================================
/*
* Copyright 2018 JessYan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jessyan.autosize;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.DisplayMetrics;
/**
* ================================================
* {@link DisplayMetrics} 封装类
*