开发过程中,一些低频使用的API不太记得,每次都要查一下。比如Build这个类。 做一个app,一边显示代码,一边显示结果,岂不美哉。
发布地址
ViewPager + TabLayout
承载多个fragment,显示不同的信息。
TabLayout字体大小改小一点。
style.xml里增加
<style name="DashPageTabText" parent="TextAppearance.AppCompat.Button">
<item name="android:textSize">10sp</item>
</style>
<style name="DashPageTabLayout" parent="Widget.Design.TabLayout">
<item name="tabTextAppearance">@style/DashPageTabText</item>
<!--<item name="tabSelectedTextColor">SELECTED TAB TEXT COLOR</item>-->
<!--<item name="tabIndicatorColor">SELECTED TAB INDICATOR COLOR</item>-->
</style>
tabLayout中增加style
<com.google.android.material.tabs.TabLayout
android:id="@+id/dash_page_tabs"
style="@style/DashPageTabLayout"
android:layout_width="match_parent"
android:layout_height="40dp" />
参考 https://stackoverflow.com/questions/31471177/text-size-of-android-design-tablayout-tabs
或者设置选中和未选中tab时文字的颜色,设置tab可以滚动
<com.google.android.material.tabs.TabLayout
android:id="@+id/dash_page_tabs"
style="@style/DashPageTabLayout"
android:layout_width="wrap_content"
android:layout_height="40dp"
app:tabMode="scrollable"
app:tabSelectedTextColor="#000"
app:tabTextColor="#99222222" />
DashPagerAdapter
类。
import android.view.View;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
public class DashPagerAdapter extends FragmentPagerAdapter {
private int fragCount;
// 装着fragment
public DashPagerAdapter(FragmentManager fm, int count) {
super(fm);
fragCount = count;
}
@Override
public int getCount() {
return fragCount;
}
@Override
public Fragment getItem(int position) {
return // 返回对应的fragment;
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return super.isViewFromObject(view, object);
}
}
onCreate里初始化
mTabLayout = findViewById(R.id.dash_page_tabs);
mViewPager = findViewById(R.id.dash_page_vp);
mTabLayout.addTab(mTabLayout.newTab().setText("Build"));
mTabLayout.addTab(mTabLayout.newTab().setText("Screen"));
mTabLayout.addTab(mTabLayout.newTab().setText("WiFi"));
mTabLayout.addTab(mTabLayout.newTab().setText("ext-Storage"));
mTabLayout.addTab(mTabLayout.newTab().setText("app-Storage"));
mTabLayout.addTab(mTabLayout.newTab().setText("uri"));
mTabLayout.addTab(mTabLayout.newTab().setText("battery"));
mDashPagerAdapter = new DashPagerAdapter(getSupportFragmentManager(), mTabLayout.getTabCount());
mViewPager.setAdapter(mDashPagerAdapter);
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mTabLayout));
mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
final int pos = tab.getPosition();
mViewPager.setCurrentItem(pos);
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
比如这样
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE)) {
mInfoReAdapter.addOrUpdate(K_SERIAL, "Build.getSerial()", Build.getSerial());
} else {
mInfoReAdapter.addOrUpdate(Build.SERIAL, "Build.SERIAL", Build.SERIAL);
}
mInfoReAdapter.addOrUpdate("Build.getRadioVersion()", "Build.getRadioVersion()", Build.getRadioVersion());
mInfoReAdapter.addOrUpdate("Build.ID ", "Build.ID", Build.ID);
// ....
mInfoReAdapter.addOrUpdate("Build.USER ", "Build.USER", Build.USER);
mInfoReAdapter.notifyDataSetChanged();
获取屏幕宽高。获取屏幕宽高的方法大约有3种,这里直接用view.post(runnable)的方式来获取实际宽高。
final View root = findViewById(R.id.container);
root.post(new Runnable() {
@Override
public void run() {
final int wid = root.getWidth();
final int height = root.getHeight();
Log.d(TAG, "phone screen size [" + wid + ", " + height + "]");
mDashPagerAdapter.setPhoneScreenSize(wid, height);
}
});
把像素转换成dp
float pxToDp(int px) {
return (px / Resources.getSystem().getDisplayMetrics().density);
}
比如获取到外部存储的路径等等。
mInfoReAdapter.addOrUpdateUpDown("root", "Environment.getRootDirectory().getAbsolutePath()",
Environment.getRootDirectory().getAbsolutePath());
展示Uri类的一些信息。
Uri uri = Uri.fromFile(getActivity().getApplicationContext().getFilesDir());
Google play console 收集到的crash信息。崩溃机型是华为和三星。
Galaxy A40 (a40), Note9 (crownlte), A70 (a70q), Note8 (greatlte);Mate 10 Pro (HWBLA)
java.lang.RuntimeException:
at android.app.ActivityThread.handleReceiver (ActivityThread.java:3586)
at android.app.ActivityThread.access$1300 (ActivityThread.java:240)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1808)
at android.os.Handler.dispatchMessage (Handler.java:106)
at android.os.Looper.loop (Looper.java:214)
at android.app.ActivityThread.main (ActivityThread.java:7094)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:494)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:975)
Caused by: java.lang.ClassNotFoundException:
at dalvik.system.BaseDexClassLoader.findClass (BaseDexClassLoader.java:134)
at java.lang.ClassLoader.loadClass (ClassLoader.java:379)
at java.lang.ClassLoader.loadClass (ClassLoader.java:312)
at android.app.AppComponentFactory.instantiateReceiver (AppComponentFactory.java:84)
at androidx.core.app.CoreComponentFactory.instantiateReceiver (CoreComponentFactory.java:56)
at android.app.ActivityThread.handleReceiver (ActivityThread.java:3579)
根据ActivityThread.handleReceiver
猜测,有一个广播接收器示例化失败了。
应用里只有一个动态注册的广播接收器。应该是注册失败了。手头上没有三星和华为。暂时没法重现。