Android开发小记
1.闪屏页
在我们什么都不做之前,一个普通的android app启动的时候都会先显示一个黑/白屏(由应用的主题决定),这个是因为android在显示第一个Activity的页面之前会先去绘制窗体等等的一些操作。
一般情况下,我们会想直接在这个空档期显示一张图片,称之为闪屏页。这里我们用一个空的Activity作为启动页并给它设置一个主题用来显示一张图片:
<activity android:name=".activity.FlushActivity"
android:screenOrientation="portrait"
android:theme="@style/FlushTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="FlushTheme" parent="AppTheme">
<item name="android:windowBackground">@drawable/flush_page</item>
</style>
之后,只需要在FlushActivity
中做一个延时跳转即可:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_flush);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Intent intent = new Intent(FlushActivity.this, WorkOrderActivity.class);
startActivity(intent);
finish();
}
}, 3000);
}
现在大家看到的app,大部分会在闪屏页展示一些广告,然后在某个小角落显示一个小小的跳过按钮或者倒计时按钮,如果是自己开发的app的话,我是肯定不会做这种设计的,每次使用一个新的app,如果它在闪屏页展示广告,这个app给我的印象就大大折扣了,即浪费了我的时间又浪费了我的心情。所以有的一些app更纯粹,根本就没有闪屏页,比如Google Play,知乎等等。
2.Activity切换动画
如果要给所有的Activity配置进入和退出动画,只需要在应用主题中配置相关的属性即可。
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:windowAnimationStyle">@style/ActivityAnim</item>
</style>
<style name="ActivityAnim">
<item name="android:activityOpenEnterAnimation">@anim/activity_in</item>
<item name="android:activityCloseExitAnimation">@anim/activity_out</item>
<item name="android:activityOpenExitAnimation">@anim/activity_no_anim</item>
<item name="android:activityCloseEnterAnimation">@anim/activity_no_anim</item>
</style>
这里的四个属性代表的意思如下:
android:activityOpenEnterAnimation:打开新的Activity并进入新的Activity时展示的动画
android:activityCloseExitAnimation:关闭当前Activity时展示的动画
android:activityOpenExitAnimation:打开新的Activity时,老的Activity消失时的动画
android:activityCloseEnterAnimation:关闭当前Activity,进入之前的Activity时展示的动画
activity_in.xml: (让Activity从屏幕的右侧滑入,一直到屏幕的左侧为止)
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="100%"
android:toXDelta="0"
android:duration="300">
</translate>
activity_out.xml: (让Activity从屏幕左侧滑动到屏幕的右侧)
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0"
android:toXDelta="100%"
android:duration="300">
</translate>
activity_no_anim.xml: (无动画,这里主要是消除另一个Activity进入或退出时动画对当前Activity的影响。)
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0"
android:toXDelta="0"
android:duration="300">
</translate>
3.修改Toolbar上图片icon的宽高
想在toolbar上显示一个宽度112dp, 高44dp的图片按钮,一开始在menu.xml中定义了一个item,设置了icon, 但是显示出来的时候这个icon太小了,模糊不清。看到有人说这里给icon设置一个drawable, 将svg图片转换成xml, 然后在xml中修改宽高即可,我自己转了以下,也修改了对应的宽高,但是显示出来的效果很诡异,所以就放弃了,其实这里可以不通过menu.xml来设置,直接在toolbar中加一个ImageView控件即可:
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:background="@color/colorPrimary">
<ImageView
android:id="@+id/img_qrorrfid"
android:layout_gravity="end"
android:layout_width="112dp"
android:layout_height="44dp"
android:scaleType="centerInside"
android:src="@mipmap/scan_qr"/>
</android.support.v7.widget.Toolbar>
4.dp和px转换
public static int dp2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
public static int px2dp(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue/scale + 0.5f);
}
5. Toast显示问题
如果连续几个Toast要显示的话,用户就要等Toast一个一个显示完,按照网上一些前辈的解决方法,可以这么写:
public class ToastUtils {
private static Toast instance;
public static void show(Context context, String message, int duration) {
if (instance == null) {
instance = Toast.makeText(context,message,duration);
} else {
instance.setText(message);
instance.setDuration(duration);
}
instance.show();
}
public static void cancel() {
if (instance != null) {
instance.cancel();
}
}
}
这样,后来的Toast就可以直接覆盖之前的Toast了,用户也不用等所有的Toast一个一个显示了。注意,这里不要频繁的cancel()
,会导致卡顿,在Activity销毁的时候调用cancel()
就可以了。
6.AndroidManifest.xml 中自定义属性
有时候一些log或者其他的一些开关,丢到代码里老忘记打包的时候去修改,后边就想把所有的开关和配置都丢到AndroidManifest.xml
里去得了。比如,开发时将网络请求参数等打印到log文件里,正式打包的时候就需要把它关掉。
在AndroidManifest.xml
的<application>
里加一个<meta-data>
节点就可以了:
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<!--**********打包时请注意修改*************-->
<!--项目中用到的一些开关-->
<meta-data android:name="com.test.logEnable" android:value="true"/>
<!--项目中用到的一些开关-->
<!--**********打包时请注意修改*************-->
</application>
然后在MyApplication
中去提供一个获取方法就可以了:
public class MyApplication extends Application {
public static MyApplication shared;
@Override
public void onCreate() {
super.onCreate();
shared = this;
}
/*- 判断是否将log写入文件中 -*/
public boolean isLogEnable() {
boolean isLogEnable = false;
ApplicationInfo applicationInfo;
try {
applicationInfo = MyApplication.this.getPackageManager()
.getApplicationInfo(MyApplication.this.getPackageName(), PackageManager.GET_META_DATA);
isLogEnable = applicationInfo.metaData.getBoolean("com.test.logEnable");
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return isLogEnable;
}
}
然后在打log的工具类里,先去判断开关的状态再去执行就可以了:
public class LogUtils {
public static void write(String message) {
if (!MyApplication.shared.isLogEnable()) {
return;
}
try {
File logFile = new File(Environment.getExternalStorageDirectory().getPath() + "/myLog.log");
String dateNow = DateFormatUtils.getString(new Date(), "yyyy-MM-dd HH:mm:ss");
String log = "【" + dateNow + "】 >>>>" + message + "<<<<<<";
FileWriter writer = new FileWriter(logFile,true);
BufferedWriter bufferedWriter = new BufferedWriter(writer);
bufferedWriter.write(log);
bufferedWriter.newLine();
bufferedWriter.newLine();
bufferedWriter.flush();
writer.close();
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
这样,以后打包的时候只要关注AndroidManifest.xml
文件就可以了。