1.效果预览
1.1.如下图所以,到目前为止所有的功能。
2.从InitApp开始->SplashActivity->MainActivity
2.1.InitApp源代码。这是整个项目的Application。
public class InitApp extends MultiDexApplication { public static Context AppContext; @Override public void onCreate(){ super.onCreate(); AppContext=getApplicationContext(); //初始化主题 initTheme(); //错误日志分析 CrashHandlerUtil.getInstance().init(AppContext); if(BuildConfig.DEBUG){ SDKManager.initStetho(AppContext); } } private void initTheme(){ } }
2.2.启动页面SplashActivity
class SplashActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val intent= Intent(this, MainActivity::class.java) startActivity(intent) finish() } }
2.3.主页面MainActivity

class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedListener { companion object { private val TAG="MainActivity" private val POSITION="position" private val SELECT_ITEM="bottomNavigationSelectItem" private val FRAGMENT_NEWS=0 private val FRAGMENT_PHOTO=1 private val FRAGMENT_VIDEO=2 private val FRAGMENT_MEDIA=3 private val REQUEST_EXTERNAL_STORAGE = 1 private val PERMISSIONS_STORAGE = arrayOf("android.permission.READ_EXTERNAL_STORAGE", "android.permission.WRITE_EXTERNAL_STORAGE") } private var newsTabLayout: NewsTabLayout?=null //新闻布局 private var photoTabLayout: PhotoTabLayout?=null //图片布局 private var videoTabLayout: VideoTabLayout?=null //视频布局 private var mediaChannelView: MediaChannelView?=null //头条号布局 private var toolbar: Toolbar?=null //标题栏 private var bottom_navigation:BottomNavigationView?=null private var exitTime:Long=0 private var position:Int=0 private var firstClickTime:Long=0 private var nav_view:NavigationView?=null private var drawer_layout:DrawerLayout?=null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) initView() verifyStoragePermissions(this) if(savedInstanceState!=null){ newsTabLayout=supportFragmentManager!!.findFragmentByTag(NewsTabLayout::class.java.name) as NewsTabLayout photoTabLayout=supportFragmentManager!!.findFragmentByTag(PhotoTabLayout::class.java.name) as PhotoTabLayout videoTabLayout=supportFragmentManager!!.findFragmentByTag(VideoTabLayout::class.java.name) as VideoTabLayout mediaChannelView=supportFragmentManager!!.findFragmentByTag(MediaChannelView::class.java.name) as MediaChannelView //恢复 recreate 前的位置 showFragment(savedInstanceState.getInt(POSITION)) bottom_navigation!!.selectedItemId=savedInstanceState.getInt(SELECT_ITEM) }else{ showFragment(FRAGMENT_NEWS) } if(SettingUtil.getInstance().getIsFirstTime()){ showTapTarget() } } private fun showTapTarget(){ val display=windowManager.defaultDisplay val target=Rect(0,display.height,0,display.height) target.offset(display.width/8,-56) val sequence=TapTargetSequence(this) .targets( TapTarget.forToolbarMenuItem(toolbar!!,R.id.action_search,"点击这里进行搜索") .dimColor(android.R.color.black) .outerCircleColor(R.color.colorPrimary) .drawShadow(true) .id(1), TapTarget.forToolbarNavigationIcon(toolbar!!,"点击这里展开侧栏") .dimColor(android.R.color.black) .outerCircleColor(R.color.colorPrimary) .drawShadow(true) .id(2), TapTarget.forBounds(target,"点击这里切换新闻 再次点击刷新当前页面") .dimColor(android.R.color.black) .outerCircleColor(R.color.colorPrimary) .targetRadius(60) .transparentTarget(true) .drawShadow(true) .id(3) ).listener(object:TapTargetSequence.Listener{ override fun onSequenceFinish() { SettingUtil.getInstance().isFirstTime=false } override fun onSequenceStep(lastTarget: TapTarget?, targetClicked: Boolean) { } override fun onSequenceCanceled(lastTarget: TapTarget?) { } }) sequence.start() } override fun initSlidable() { //禁止滑动返回 //什么都不写就行了 } override fun onSaveInstanceState(outState: Bundle?) { outState!!.putInt(POSITION,position) outState!!.putInt(SELECT_ITEM,bottom_navigation!!.selectedItemId) } private fun initView(){ toolbar=findViewById(R.id.toolbar) as Toolbar toolbar!!.inflateMenu(R.menu.menu_activity_main) bottom_navigation=findViewById(R.id.bottom_navigation) as BottomNavigationView //解决只有图标没有文字的问题 BottomNavigationViewHelper.disableShiftMode(bottom_navigation) setSupportActionBar(toolbar) setTitle(R.string.title_news) bottom_navigation!!.setOnNavigationItemSelectedListener{ item -> when(item.itemId){ R.id.action_news -> { showFragment(FRAGMENT_NEWS) doubleClick(FRAGMENT_NEWS) } R.id.action_photo -> { showFragment(FRAGMENT_PHOTO) doubleClick(FRAGMENT_PHOTO) } R.id.action_video -> { showFragment(FRAGMENT_VIDEO) doubleClick(FRAGMENT_VIDEO) } R.id.action_media -> { showFragment(FRAGMENT_MEDIA) } } true } drawer_layout=findViewById(R.id.drawer_layout) as DrawerLayout val toggle=ActionBarDrawerToggle(this,drawer_layout,toolbar,R.string.navigation_drawer_open,R.string.navigation_drawer_close) drawer_layout!!.addDrawerListener(toggle) toggle.syncState() nav_view=findViewById(R.id.nav_view) as NavigationView nav_view!!.setNavigationItemSelectedListener(this) } fun doubleClick(index:Int){ val secondClickTime=System.currentTimeMillis() if((secondClickTime-firstClickTime)<500){ when(index){ FRAGMENT_NEWS -> { } FRAGMENT_PHOTO ->{ } FRAGMENT_VIDEO -> { } } }else{ firstClickTime=secondClickTime } } private fun showFragment(index:Int){ val ft=supportFragmentManager.beginTransaction() hideFragment(ft) position=index when(index){ FRAGMENT_NEWS -> { toolbar!!.setTitle(R.string.title_news) if(newsTabLayout==null){ newsTabLayout = NewsTabLayout.getInstance() ft.add(R.id.container, newsTabLayout, NewsTabLayout::class.java.name) }else{ ft.show(newsTabLayout) } } FRAGMENT_PHOTO -> { toolbar!!.setTitle(R.string.title_photo) if(photoTabLayout==null){ photoTabLayout = PhotoTabLayout.getInstance() ft.add(R.id.container, photoTabLayout, PhotoTabLayout::class.java.name) }else{ ft.show(photoTabLayout) } } FRAGMENT_VIDEO -> { toolbar!!.setTitle(R.string.title_video) if(videoTabLayout==null){ videoTabLayout = VideoTabLayout.getInstance() ft.add(R.id.container, videoTabLayout, VideoTabLayout::class.java.name) }else{ ft.show(videoTabLayout) } } FRAGMENT_MEDIA -> { toolbar!!.setTitle(R.string.title_media) if(mediaChannelView==null){ }else{ } } } ft.commit() } private fun hideFragment(ft:FragmentTransaction){ //如果不为空,就先隐藏起来 if(newsTabLayout!=null){ ft.hide(newsTabLayout) } if(photoTabLayout!=null){ ft.hide(photoTabLayout) } if(videoTabLayout!=null){ ft.hide(videoTabLayout) } if(mediaChannelView!=null){ ft.hide(mediaChannelView as Fragment) } } override fun onBackPressed() { //再次点击退出 val currentTime=System.currentTimeMillis() if((currentTime-exitTime)<2000){ super.onBackPressed() }else{ Toast.makeText(this,R.string.double_click_exit,Toast.LENGTH_SHORT).show() exitTime=currentTime } } override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.menu_activity_main, menu) return true } override fun onOptionsItemSelected(item: MenuItem): Boolean { if (item.itemId == R.id.action_search) { //跳转到搜索页面 } return super.onOptionsItemSelected(item) } override fun onNavigationItemSelected(item: MenuItem): Boolean { // val id=item.itemId when(id){ R.id.nav_switch_night_mode ->{ } R.id.nav_setting ->{ } R.id.nav_share -> { } } return false } fun verifyStoragePermissions(activity: Activity) { try { //检测是否有写的权限 val permission = ActivityCompat.checkSelfPermission(activity, "android.permission.WRITE_EXTERNAL_STORAGE") if (permission != PackageManager.PERMISSION_GRANTED) { // 没有写的权限,去申请写的权限,会弹出对话框 ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE) } } catch (e: Exception) { e.printStackTrace() } } }
2.4.MainActivity布局

<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:openDrawer="start" > <android.support.design.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent" > <include layout="@layout/toolbar"/> <include layout="@layout/container"/> <android.support.design.widget.BottomNavigationView android:id="@+id/bottom_navigation" style="@style/Widget.Design.BottomNavigationView" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_gravity="bottom" android:background="@color/viewBackground" app:elevation="16dp" app:itemIconTint="@drawable/nav_item_color_state" app:itemTextColor="@drawable/nav_item_color_state" app:menu="@menu/bottom_navigation_main" /> </android.support.design.widget.CoordinatorLayout> <android.support.design.widget.NavigationView android:id="@+id/nav_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" android:fitsSystemWindows="true" app:headerLayout="@layout/nav_header_main" app:menu="@menu/nav_menu" /> </android.support.v4.widget.DrawerLayout>
@layout/toolbar布局

<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/AppBarLayout01" android:layout_width="match_parent" android:layout_height="wrap_content" android:fitsSystemWindows="false" android:theme="@style/AppTheme.AppBarOverlay" app:elevation="0dp" > <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_scrollFlags="scroll|enterAlways" app:popupTheme="@style/AppTheme.PopupOverlay" /> </android.support.design.widget.AppBarLayout>
@layout/container布局

<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/viewBackground" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:layout="@layout/fragment_news_tab" > </FrameLayout>
2.5.BaseActivity为基类

public class BaseActivity extends RxAppCompatActivity { private static final String TAG="BaseActivity"; protected SlidrInterface slidrInterface; private int iconType=-1; @Override protected void onCreate(@Nullable Bundle savedInstanceState){ super.onCreate(savedInstanceState); //默认图标获取的是圆形circle this.iconType=SettingUtil.getInstance().getCustomIconValue(); initSlidable(); } @Override protected void onResume(){ super.onResume(); //获取主题色 int color=SettingUtil.getInstance().getColor(); //获取图标形状,圆,矩,正 int drawable=Constant.ICONS_DRAWABLES[SettingUtil.getInstance().getCustomIconValue()]; if(getSupportActionBar()!=null){ //设置标题栏的颜色 getSupportActionBar().setBackgroundDrawable(new ColorDrawable(color)); } //如果SDK版本>=21,还要设置状态栏的颜色 if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP){ getWindow().setStatusBarColor(CircleView.shiftColorDown(color)); //TaskDescription==>用于在最近的任务列表中设置和检索当前活动的信息 ActivityManager.TaskDescription taskDescription=new ActivityManager.TaskDescription( getString(R.string.app_name), BitmapFactory.decodeResource(getResources(),drawable), color ); setTaskDescription(taskDescription); //setNavigationBar是底部导航栏,模拟器上会有 if(SettingUtil.getInstance().getNavBar()){ getWindow().setNavigationBarColor(CircleView.shiftColorDown(color)); }else{ getWindow().setNavigationBarColor(Color.BLACK); } } } @Override public boolean onOptionsItemSelected(MenuItem item){ if(item.getItemId()==android.R.id.home){ onBackPressed(); } return super.onOptionsItemSelected(item); } @Override public void onBackPressed(){ //Fragment逐个出栈 int count=getSupportFragmentManager().getBackStackEntryCount(); if(count==0){ super.onBackPressed(); }else{ getSupportFragmentManager().popBackStack(); } } @Override protected void onStop(){ //如果iconType不为默认的圆形了 if(iconType!=SettingUtil.getInstance().getCustomIconValue()){ new Thread(new Runnable() { @Override public void run() { //前提是在清单中已经完成配置别名 String act=".SplashActivity_"; for(String s:Constant.ICONS_TYPE){ getPackageManager().setComponentEnabledSetting(new ComponentName(BaseActivity.this,getPackageName()+act+s), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); } act+=Constant.ICONS_TYPE[SettingUtil.getInstance().getCustomIconValue()]; getPackageManager().setComponentEnabledSetting(new ComponentName(BaseActivity.this,getPackageName()+act), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); } }).start(); } super.onStop(); } /** * 初始化Toolbar */ protected void initToolbar(Toolbar toolbar, boolean homeAsUpEnabled, String title){ toolbar.setTitle(title); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(homeAsUpEnabled); } /** * 初始化滑动返回 */ protected void initSlidable(){ int isSlidable=SettingUtil.getInstance().getSlidable(); if(isSlidable!= Constant.SLIDABLE_DISABLE){ SlidrConfig config=new SlidrConfig.Builder() .edge(isSlidable==Constant.SLIDABLE_EDGE) .build(); slidrInterface= Slidr.attach(this,config); } } }
2.6.常量定义类

public class Constant { public static final String USER_AGENT_MOBILE="Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Mobile Safari/537.36"; public static final String USER_AGENT_PC="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"; public static final int[] TAG_COLORS = new int[]{ Color.parseColor("#90C5F0"), Color.parseColor("#91CED5"), Color.parseColor("#F88F55"), Color.parseColor("#C0AFD0"), Color.parseColor("#E78F8F"), Color.parseColor("#67CCB7"), Color.parseColor("#F6BC7E") }; public static final int[] ICONS_DRAWABLES = new int[]{ R.mipmap.ic_launcher_circle, R.mipmap.ic_launcher_rect, R.mipmap.ic_launcher_square }; public static final String[] ICONS_TYPE=new String[]{"circle","rect","square"}; public static final int SLIDABLE_DISABLE=0; public static final int SLIDABLE_EDGE=1; public static final int SLIDABLE_FULL=2; public static final String AS="as"; public static final String CP="cp"; public static final int NEWS_CHANNEL_ENABLE=1; public static final int NEWS_CHANNEL_DISABLE=0; }
2.7.方便开发者测试类SDKManager

package com.jasonjan.headnews.global; import android.content.Context; import com.facebook.stetho.Stetho; import okhttp3.OkHttpClient; import okhttp3.logging.HttpLoggingInterceptor; /** * Created by JasonJan on 2017/11/30. */ public class SDKManager { public static void initStetho(Context context){ Stetho.initializeWithDefaults(context); } public static OkHttpClient.Builder initInterceptor(OkHttpClient.Builder builder){ HttpLoggingInterceptor interceptor=new HttpLoggingInterceptor(); interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); builder.addInterceptor(interceptor); return builder; } }
2.8.异常处理类CrashHandleUtil

package com.jasonjan.headnews.util; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Build; import android.os.Environment; import android.os.Process; import android.util.Log; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Date; /** * Created by JasonJan on 2017/12/2. */ public class CrashHandlerUtil implements Thread.UncaughtExceptionHandler { private static final String TAG = "异常处理"; private static final boolean DEBUG = true; private static final String PATH = Environment.getExternalStorageDirectory().getPath() + "/toutiao/log/"; private static final String FILE_NAME = "crash"; //log文件的后缀名 private static final String FILE_NAME_SUFFIX = ".txt"; private static CrashHandlerUtil sInstance = new CrashHandlerUtil(); //系统默认的异常处理(默认情况下,系统会终止当前的异常程序) private Thread.UncaughtExceptionHandler mDefaultCrashHandler; private Context mContext; //构造方法私有,防止外部构造多个实例,即采用单例模式 private CrashHandlerUtil() { } public static CrashHandlerUtil getInstance() { return sInstance; } //这里主要完成初始化工作 public void init(Context context) { //获取系统默认的异常处理器 mDefaultCrashHandler = Thread.getDefaultUncaughtExceptionHandler(); //将当前实例设为系统默认的异常处理器 Thread.setDefaultUncaughtExceptionHandler(this); //获取Context,方便内部使用 mContext = context.getApplicationContext(); } /** * 这个是最关键的函数,当程序中有未被捕获的异常,系统将会自动调用#uncaughtException方法 * thread为出现未捕获异常的线程,ex为未捕获的异常,有了这个ex,我们就可以得到异常信息。 */ @Override public void uncaughtException(Thread thread, Throwable ex) { try { //导出异常信息到SD卡中 dumpExceptionToSDCard(ex); //这里可以通过网络上传异常信息到服务器,便于开发人员分析日志从而解决bug uploadExceptionToServer(); } catch (IOException e) { e.printStackTrace(); } //打印出当前调用栈信息 ex.printStackTrace(); //如果系统提供了默认的异常处理器,则交给系统去结束我们的程序,否则就由我们自己结束自己 if (mDefaultCrashHandler != null) { mDefaultCrashHandler.uncaughtException(thread, ex); } else { Process.killProcess(Process.myPid()); } } private void dumpExceptionToSDCard(Throwable ex) throws IOException { //如果SD卡不存在或无法使用,则无法把异常信息写入SD卡 if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { if (DEBUG) { Log.w(TAG, "sdcard unmounted,skip dump exception"); return; } } File dir = new File(PATH); if (!dir.exists()) { dir.mkdirs(); } long current = System.currentTimeMillis(); String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(current)); //以当前时间创建log文件 File file = new File(PATH + FILE_NAME + time + FILE_NAME_SUFFIX); if (!file.exists()) { Log.i(TAG, "文件名称为:"+file.getName()); }else{ Log.i(TAG, "文件名称为:"+file.getName()); } try { if(file.createNewFile()){ Log.i(TAG, "文件创建成功:名称为:"+file.getName()); } if(file.exists()){ Log.i(TAG, "文件exists"); } PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file))); //导出发生异常的时间 pw.println(time); //导出手机信息 dumpPhoneInfo(pw); pw.println(); //导出异常的调用栈信息 ex.printStackTrace(pw); pw.close(); } catch (Exception e) { Log.e(TAG, "dump crash info failed"); } } private void dumpPhoneInfo(PrintWriter pw) throws PackageManager.NameNotFoundException { //应用的版本名称和版本号 PackageManager pm = mContext.getPackageManager(); PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager .GET_ACTIVITIES); pw.print("App Version: "); pw.print(pi.versionName); pw.print('_'); pw.println(pi.versionCode); //android版本号 pw.print("OS Version: "); pw.print(Build.VERSION.RELEASE); pw.print("_"); pw.println(Build.VERSION.SDK_INT); //手机制造商 pw.print("Vendor: "); pw.println(Build.MANUFACTURER); //手机型号 pw.print("Model: "); pw.println(Build.MODEL); //cpu架构 pw.print("CPU ABI: "); pw.println(Build.CPU_ABI); } private void uploadExceptionToServer() { //TODO Upload Exception Message To Your Web Server } }
2.9.网络工具类NetWorkUtil

package com.jasonjan.headnews.util; import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkInfo; /** * Created by JasonJan on 2017/11/30. */ public class NetWorkUtil { public static boolean isNetWorkConnected(Context context){ if(context!=null){ ConnectivityManager manager=(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo=manager.getActiveNetworkInfo(); return null != networkInfo&&networkInfo.isAvailable(); } return false; } public static boolean isWifiConnected(Context context){ if(context!=null){ ConnectivityManager manager=(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo netWorkInfo=manager.getActiveNetworkInfo(); if(null!=netWorkInfo&&netWorkInfo.getType()==ConnectivityManager.TYPE_WIFI){ return netWorkInfo.isAvailable(); } } return false; } public static boolean isMobileConnected(Context context){ if(context!=null){ ConnectivityManager manager=(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo=manager.getActiveNetworkInfo(); if(null!=networkInfo&&networkInfo.getType()==ConnectivityManager.TYPE_MOBILE){ return networkInfo.isAvailable(); } } return false; } }
2.10.项目设置通用类

package com.jasonjan.headnews.util; import android.content.SharedPreferences; import android.graphics.Color; import android.preference.PreferenceManager; import com.jasonjan.headnews.R; import com.jasonjan.headnews.global.InitApp; /** * Created by JasonJan on 2017/11/30. */ public class SettingUtil { private SharedPreferences setting= PreferenceManager.getDefaultSharedPreferences(InitApp.AppContext); private static final class SettingUtilInstance{ private static final SettingUtil instance=new SettingUtil(); } public static SettingUtil getInstance(){ return SettingUtilInstance.instance; } /** * 获取是否开启无图模式 * @return */ public boolean getIsNoPhotoMode(){ return setting.getBoolean("switch_noPhotoMode",false)&& NetWorkUtil.isMobileConnected(InitApp.AppContext); } /** * 获取主题颜色 * @return */ public int getColor(){ int defaultColor=InitApp.AppContext.getResources().getColor(R.color.colorPrimary); int color=setting.getInt("color",defaultColor); if((color!=0)&& Color.alpha(color)!=255){ return defaultColor; } return color; } /** * 设置主题颜色 * @param color */ public void setColor(int color){ setting.edit().putInt("color",color).apply(); } /** * 获取是否开启夜间模式 * @return */ public boolean getIsNightMode(){ return setting.getBoolean("switch_nightMode",false); } /** * 设置夜间模式 * @param flag */ public void setIsNightMode(boolean flag){ setting.edit().putBoolean("switch_nightMode",flag).apply(); } /** * 获取是否开启自动切换夜间模式 * @return */ public boolean getIsAutoNightMode(){ return setting.getBoolean("auto_nightMode",false); } /** * 设置开启自动切换夜间模式 * @param flag */ public void setIsAutoNightMode(boolean flag){ setting.edit().putBoolean("auto_nightMode",flag).apply(); } public String getNightStartHour(){ return setting.getString("night_startHour","22"); } public void setNightStartHour(String nightStartHour){ setting.edit().putString("night_startHour",nightStartHour).apply(); } public String getNightStartMinute(){ return setting.getString("night_startMinute","00"); } public void setNightStartMinute(String nightStartMinute){ setting.edit().putString("night_startMinute",nightStartMinute).apply(); } public String getDayStartHour(){ return setting.getString("day_startHour","06"); } public void setDayStartHour(String day_startHour){ setting.edit().putString("day_startHour",day_startHour).apply(); } public String getDayStartMinute(){ return setting.getString("day_startMinute","00"); } public void setDayStartMinute(String day_startMinute){ setting.edit().putString("day_startMinute",day_startMinute).apply(); } /** * 获取是否开启导航栏上色 * @return */ public boolean getNavBar(){ return setting.getBoolean("nav_bar",false); } /** * 获取是否开启视频强制横屏 * @return */ public boolean getIsVideoForceLandscape(){ return setting.getBoolean("video_force_landscape",false); } /** * 获取图标值 * @return */ public int getCustomIconValue(){ String s=setting.getString("custom_icon","0"); return Integer.parseInt(s); } /** * 获取滑动返回值 * @return */ public int getSlidable(){ String s=setting.getString("slidable","1"); return Integer.parseInt(s); } /** * 获取是否开启视频自动播放 * @return */ public boolean getIsVideoAutoPlay(){ return setting.getBoolean("video_auto_play",false)&&NetWorkUtil.isWifiConnected(InitApp.AppContext); } /** * 获取字体大小 * @return */ public int getTextSize(){ return setting.getInt("textsize",16); } /** * 设置字体大小 * @param textSize */ public void setTextSize(int textSize){ setting.edit().putInt("textsize",textSize).apply(); } public boolean getIsFirstTime(){ return setting.getBoolean("first_time",true); } public void setIsFirstTime(boolean flag){ setting.edit().putBoolean("first_time",flag).apply(); } }
2.11.设置底部导航文字不消失

package com.jasonjan.headnews.widget; import android.support.design.internal.BottomNavigationItemView; import android.support.design.internal.BottomNavigationMenuView; import android.support.design.widget.BottomNavigationView; import android.util.Log; import java.lang.reflect.Field; /** * Created by JasonJan on 2017/12/1. */ public class BottomNavigationViewHelper { public static void disableShiftMode(BottomNavigationView view) { BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0); try { Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode"); shiftingMode.setAccessible(true); shiftingMode.setBoolean(menuView, false); shiftingMode.setAccessible(false); for (int i = 0; i < menuView.getChildCount(); i++) { BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i); //noinspection RestrictedApi item.setShiftingMode(false); // set once again checked value, so view will be updated //noinspection RestrictedApi item.setChecked(item.getItemData().isChecked()); } } catch (NoSuchFieldException e) { Log.e("BNVHelper", "Unable to get shift mode field", e); } catch (IllegalAccessException e) { Log.e("BNVHelper", "Unable to change value of shift mode", e); } } }
3.子片段
3.1.NewsTabLayout新闻片段

package com.jasonjan.headnews.module.news; import android.os.Bundle; import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; import android.support.v4.view.ViewPager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; import com.jasonjan.headnews.R; import com.jasonjan.headnews.module.base.BasePagerAdapter; import com.jasonjan.headnews.test.Test_Fragment; import com.jasonjan.headnews.util.SettingUtil; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import android.support.annotation.Nullable; import io.reactivex.Observable; /** * Created by JasonJan on 2017/12/1. */ public class NewsTabLayout extends Fragment { public static final String TAG="NewsTabLayout"; private static NewsTabLayout instance=null; private ViewPager viewPager; private BasePagerAdapter adapter; private LinearLayout linearLayout; //private NewsChannelDao dao=new NewsChannelDao(); private List<Fragment> fragmentList; private List<String> titleList; private Observable<Boolean> observable; private Map<String,Fragment> map=new HashMap<>(); public static NewsTabLayout getInstance(){ if(instance==null){ instance=new NewsTabLayout(); } return instance; } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_news_tab, container, false); initView(view); initData(); return view; } @Override public void onResume() { super.onResume(); linearLayout.setBackgroundColor(SettingUtil.getInstance().getColor()); } public void initView(View view){ TabLayout tab_layout=view.findViewById(R.id.tab_layout_news); viewPager=view.findViewById(R.id.view_pager_news); tab_layout.setupWithViewPager(viewPager); tab_layout.setTabMode(TabLayout.MODE_SCROLLABLE); ImageView add_channel_iv=view.findViewById(R.id.add_chnnel_iv); add_channel_iv.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v){ //设置点击事件 } }); linearLayout=view.findViewById(R.id.header_layout); linearLayout.setBackgroundColor(SettingUtil.getInstance().getColor()); } public void initData(){ fragmentList = new ArrayList<>(); titleList = new ArrayList<>(); fragmentList.add(new Test_Fragment()); titleList.add("推荐"); fragmentList.add(new Test_Fragment()); titleList.add("热点"); fragmentList.add(new Test_Fragment()); titleList.add("视频"); fragmentList.add(new Test_Fragment()); titleList.add("社会"); fragmentList.add(new Test_Fragment()); titleList.add("娱乐"); adapter = new BasePagerAdapter(getChildFragmentManager(), fragmentList, titleList); viewPager.setAdapter(adapter); viewPager.setOffscreenPageLimit(15); } }
3.2.NewsTabLayout布局代码

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:id="@+id/header_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <android.support.design.widget.TabLayout android:id="@+id/tab_layout_news" style="@style/TabLayout" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:minHeight="?attr/actionBarSize" android:theme="@style/AppTheme.AppBarOverlay" app:tabTextColor="@color/gray" /> <ImageView android:id="@+id/add_chnnel_iv" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="center" android:background="?attr/selectableItemBackground" android:foreground="?attr/selectableItemBackground" android:maxHeight="?attr/actionBarSize" android:paddingBottom="4dp" android:paddingLeft="10dp" android:paddingRight="10dp" android:paddingTop="4dp" android:scaleType="center" app:srcCompat="@drawable/ic_add_white_24dp" tools:ignore="ContentDescription" /> </LinearLayout> <android.support.v4.view.ViewPager android:id="@+id/view_pager_news" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:layout="@layout/fragment_list"> </android.support.v4.view.ViewPager> </LinearLayout>
3.3.PhotoTabLayout图片片段

package com.jasonjan.headnews.module.photo; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; import android.support.v4.view.ViewPager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.jasonjan.headnews.R; import com.jasonjan.headnews.global.InitApp; import com.jasonjan.headnews.module.base.BasePagerAdapter; import com.jasonjan.headnews.test.Test_Fragment; import com.jasonjan.headnews.util.SettingUtil; import java.util.ArrayList; import java.util.List; /** * Created by JasonJan on 2017/12/1. */ public class PhotoTabLayout extends Fragment { private static final String TAG = "PhotoTabLayout"; private static PhotoTabLayout instance = null; private static int pageSize = InitApp.AppContext.getResources().getStringArray(R.array.photo_id).length; private String categoryId[] = InitApp.AppContext.getResources().getStringArray(R.array.photo_id); private String categoryName[] = InitApp.AppContext.getResources().getStringArray(R.array.photo_name); private TabLayout tabLayout; private ViewPager viewPager; private List<Fragment> fragmentList = new ArrayList<>(); private BasePagerAdapter adapter; public static PhotoTabLayout getInstance() { if (instance == null) { instance = new PhotoTabLayout(); } return instance; } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_photo_tab, container, false); initView(view); initData(); return view; } @Override public void onResume() { super.onResume(); tabLayout.setBackgroundColor(SettingUtil.getInstance().getColor()); } private void initView(View view){ tabLayout = view.findViewById(R.id.tab_layout_photo); viewPager = view.findViewById(R.id.view_pager_photo); tabLayout.setupWithViewPager(viewPager); tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE); tabLayout.setBackgroundColor(SettingUtil.getInstance().getColor()); viewPager.setOffscreenPageLimit(pageSize); } private void initData(){ for (int i = 0; i < categoryId.length; i++) { Fragment fragment = new Test_Fragment();//这里需要更改 fragmentList.add(fragment); } adapter = new BasePagerAdapter(getChildFragmentManager(), fragmentList, categoryName); viewPager.setAdapter(adapter); } @Override public void onDestroy() { if (instance != null) { instance = null; } super.onDestroy(); } }
3.4.PhotoTabLayout布局代码

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.design.widget.TabLayout android:id="@+id/tab_layout_photo" style="@style/TabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="?attr/actionBarSize" android:theme="@style/AppTheme.AppBarOverlay" app:tabTextColor="@color/gray"> </android.support.design.widget.TabLayout> <android.support.v4.view.ViewPager android:id="@+id/view_pager_photo" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:layout="@layout/fragment_list"> </android.support.v4.view.ViewPager> </LinearLayout>
3.5.VideoTabLayout视频片段

package com.jasonjan.headnews.module.video; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; import android.support.v4.view.ViewPager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.jasonjan.headnews.R; import com.jasonjan.headnews.global.InitApp; import com.jasonjan.headnews.module.base.BasePagerAdapter; import com.jasonjan.headnews.test.Test_Fragment; import com.jasonjan.headnews.util.SettingUtil; import java.util.ArrayList; import java.util.List; /** * Created by JasonJan on 2017/12/1. */ public class VideoTabLayout extends Fragment { private static VideoTabLayout instance = null; private static int pageSize = InitApp.AppContext.getResources().getStringArray(R.array.mobile_video_id).length; private String categoryId[] = InitApp.AppContext.getResources().getStringArray(R.array.mobile_video_id); private String categoryName[] = InitApp.AppContext.getResources().getStringArray(R.array.mobile_video_name); private TabLayout tabLayout; private ViewPager viewPager; private List<Fragment> fragmentList = new ArrayList<>(); private BasePagerAdapter adapter; public static VideoTabLayout getInstance() { if (instance == null) { instance = new VideoTabLayout(); } return instance; } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_video_tab, container, false); initView(view); initData(); return view; } @Override public void onResume() { super.onResume(); tabLayout.setBackgroundColor(SettingUtil.getInstance().getColor()); } private void initView(View view) { tabLayout = view.findViewById(R.id.tab_layout_video); viewPager = view.findViewById(R.id.view_pager_video); tabLayout.setupWithViewPager(viewPager); tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE); tabLayout.setBackgroundColor(SettingUtil.getInstance().getColor()); viewPager.setOffscreenPageLimit(pageSize); } private void initData() { for (int i = 0; i < categoryId.length; i++) { Fragment fragment = new Test_Fragment();//这里需要更改 fragmentList.add(fragment); } adapter = new BasePagerAdapter(getChildFragmentManager(), fragmentList, categoryName); viewPager.setAdapter(adapter); } @Override public void onDestroy() { if (instance != null) { instance = null; } super.onDestroy(); } }
3.6.VideoTabLayout布局代码

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.design.widget.TabLayout android:id="@+id/tab_layout_video" style="@style/TabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="?attr/actionBarSize" android:theme="@style/AppTheme.AppBarOverlay" app:tabTextColor="@color/gray"> </android.support.design.widget.TabLayout> <android.support.v4.view.ViewPager android:id="@+id/view_pager_video" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:layout="@layout/fragment_list"> </android.support.v4.view.ViewPager> </LinearLayout>
3.7.整理片段的适配器

package com.jasonjan.headnews.module.base; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; import android.support.v4.view.PagerAdapter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Created by JasonJan on 2017/12/3. */ public class BasePagerAdapter extends FragmentStatePagerAdapter { private List<Fragment> fragmentList; private List<String> titleList; public BasePagerAdapter(FragmentManager fm, List<Fragment> fragmentList, String[] titles) { super(fm); this.fragmentList = fragmentList; this.titleList = new ArrayList<>(Arrays.asList(titles)); } public BasePagerAdapter(FragmentManager fm, List<Fragment> fragmentList, List<String> titleList) { super(fm); this.fragmentList = fragmentList; this.titleList = titleList; } @Override public Fragment getItem(int position) { return fragmentList.get(position); } @Override public int getCount() { return titleList.size(); } @Override public CharSequence getPageTitle(int position) { return titleList.get(position); } @Override public int getItemPosition(Object object) { return PagerAdapter.POSITION_NONE; } //刷新一下整个List public void recreateItems(List<Fragment> fragmentList,List<String> titleList){ this.fragmentList=fragmentList; this.titleList=titleList; notifyDataSetChanged(); } }
3.8.测试片段代码

package com.jasonjan.headnews.test; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.jasonjan.headnews.R; /** * Created by JasonJan on 2017/12/3. */ public class Test_Fragment extends Fragment { @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.test_fragment, container, false); return view; } }
3.9.测试片段布局代码

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:background="@color/Grey50" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/test_fragment_txt1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="这是..." android:layout_centerInParent="true" android:textSize="50dp" /> </RelativeLayout>
4.一些资源文件
4.1.底部导航栏菜单样式
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/action_news" android:enabled="true" android:icon="@drawable/ic_newspaper_white_24dp" android:title="@string/title_news" app:showAsAction="ifRoom"/> <item android:id="@+id/action_photo" android:enabled="true" android:icon="@drawable/ic_gallery_white_24dp" android:title="@string/title_photo" app:showAsAction="ifRoom"/> <item android:id="@+id/action_video" android:enabled="true" android:icon="@drawable/ic_youtube_white_24dp" android:title="@string/title_video" app:showAsAction="ifRoom"/> <item android:id="@+id/action_media" android:enabled="true" android:icon="@drawable/ic_library_books_white_24dp" android:title="@string/title_media" app:showAsAction="ifRoom"/> </menu>
4.2.顶部搜索菜单布局
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/action_search" android:icon="@drawable/ic_search_white_24dp" android:title="@string/action_search" app:showAsAction="always|collapseActionView"/> </menu>
4.3.侧边栏菜单布局
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <group android:id="@+id/other"> <item android:id="@+id/nav_switch_night_mode" android:icon="@drawable/ic_night_gray_24dp" android:title="@string/nav_switch_night_mode"/> <item android:id="@+id/nav_setting" android:icon="@drawable/ic_setting_gray_24dp" android:title="@string/nav_setting"/> <item android:id="@+id/nav_share" android:icon="@drawable/ic_share_grey_24dp" android:title="@string/nav_share"/> </group> </menu>
4.4.颜色资源文件==>color.xml

<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#E91E63</color> <color name="colorPrimaryDark">#C2185B</color> <color name="colorAccent">#FF5252</color> <color name="textColorPrimary">#616161</color> <color name="viewBackground">@android:color/white</color> <color name="windowBackground">@color/Grey100</color> <color name="line_divider">@color/Grey300</color> <color name="colorPrimary_night">#35464e</color> <color name="colorPrimaryDark_night">#212a2f</color> <color name="colorAccent_night">#212a2f</color> <color name="textColorPrimary_night">#616161</color> <color name="viewBackground_night">#212a2f</color> <color name="White">#FFFFFF</color> <color name="Black">#000000</color> <color name="Red">#f44336</color> <color name="Pink">#e91e63</color> <color name="Purple">#9c27b0</color> <color name="Deep_Purple">#673ab7</color> <color name="Indigo">#3f51b5</color> <color name="Blue">#2196f3</color> <color name="Light_Blue">#03a9f4</color> <color name="Cyan">#00bcd4</color> <color name="Teal">#009688</color> <color name="Green">#4caf50</color> <color name="Light_Green">#8bc34a</color> <color name="Lime">#cddc39</color> <color name="Yellow">#ffeb3b</color> <color name="Amber">#ffc107</color> <color name="Orange">#ff9800</color> <color name="Deep_Orange">#ff5722</color> <color name="Brown">#795548</color> <color name="Grey">#9e9e9e</color> <color name="Blue_Grey">#607d8b</color> <color name="gray">#9cffffff</color> <color name="dkgray">#8f8989</color> <color name="NULL">#00FFFFFF</color> <color name="shadow_material_light">#727272</color> <color name="Grey50">#FAFAFA</color> <color name="Grey100">#F5F5F5</color> <color name="Grey200">#EEEEEE</color> <color name="Grey300">#E0E0E0</color> <color name="Grey400">#bdbdbd</color> <color name="Grey500">#9e9e9e</color> <color name="Grey600">#757575</color> <color name="Grey700">#616161</color> <color name="Grey800">#424242</color> <color name="Grey900">#212121</color> </resources>
4.5.type分类==>视频类型分类==>mobile_video_category.xml

<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="mobile_video_name"> <item>推荐</item> <item>音乐</item> <item>搞笑</item> <item>社会</item> <item>小品</item> <item>生活</item> <item>影视</item> <item>娱乐</item> <item>呆萌</item> <item>游戏</item> <item>原创</item> <item>开眼</item> </string-array> <string-array name="mobile_video_id"> <item>video</item> <item>subv_voice</item> <item>subv_funny</item> <item>subv_society</item> <item>subv_comedy</item> <item>subv_life</item> <item>subv_movie</item> <item>subv_entertainment</item> <item>subv_cute</item> <item>subv_game</item> <item>subv_boutique</item> <item>subv_broaden_view</item> </string-array> </resources>
4.6.图片类型分类==>photo_category.xml

<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="photo_name"> <item>全部</item> <item>老照片</item> <item>故事照片</item> <item>摄影集</item> </string-array> <string-array name="photo_id"> <item>组图</item> <item>gallery_old_picture</item> <item>gallery_story</item> <item>gallery_photograthy</item> </string-array> </resources>
4.7.styles.xml

<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.DayNight.DarkActionBar"> <!--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="AppTheme.NoActionBar"> <item name="windowActionBar">false</item> <item name="windowNoTitle">true</item> </style> <style name="SplashTheme" parent="AppTheme.NoActionBar"> <item name="android:windowBackground">@drawable/bg_splash</item> </style> <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/> <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light"/> <style name="TabLayout" parent="Base.Widget.Design.TabLayout"> <item name="tabMaxWidth">@dimen/design_tab_max_width</item> <item name="tabIndicatorColor">#FFFFFF</item> <item name="tabIndicatorHeight">2dp</item> <item name="tabPaddingStart">12dp</item> <item name="tabPaddingEnd">12dp</item> <item name="tabBackground">?attr/selectableItemBackground</item> <item name="tabTextAppearance">@style/TextAppearance.Design.Tab</item> <item name="tabSelectedTextColor">?android:textColorPrimary</item> </style> </resources>
4.8.清单资源文件==>AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.jasonjan.headnews"> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permission-sdk-23 android:name="android.permission.INTERNET"/> <uses-permission-sdk-23 android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission-sdk-23 android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission-sdk-23 android:name="android.permission.ACCESS_WIFI_STATE"/> <application android:name=".global.InitApp" android:allowBackup="true" android:icon="@mipmap/ic_launcher_circle" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".global.SplashActivity" android:configChanges="orientation|screenSize|uiMode" android:label="@string/app_name" android:theme="@style/SplashTheme" > <intent-filter> <action android:name="android.intent.action.MAIN" /> </intent-filter> </activity> <activity-alias android:name=".global.SplashActivity_circle" android:label="@string/app_name" android:enabled="true" android:icon="@mipmap/ic_launcher_circle" android:targetActivity=".global.SplashActivity" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity-alias> <activity-alias android:name=".global.SplashActivity_rect" android:label="@string/app_name" android:enabled="false" android:icon="@mipmap/ic_launcher_rect" android:targetActivity=".global.SplashActivity" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity-alias> <activity-alias android:name=".global.SplashActivity_square" android:label="@string/app_name" android:enabled="false" android:icon="@mipmap/ic_launcher_square" android:targetActivity=".global.SplashActivity" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity-alias> <activity android:name=".main.MainActivity" android:configChanges="orientation|screenSize|uiMode" android:label="@string/app_name" android:theme="@style/AppTheme.NoActionBar" /> </application> </manifest>
4.9.build.gradle

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.jasonjan.headnews"> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permission-sdk-23 android:name="android.permission.INTERNET"/> <uses-permission-sdk-23 android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission-sdk-23 android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission-sdk-23 android:name="android.permission.ACCESS_WIFI_STATE"/> <application android:name=".global.InitApp" android:allowBackup="true" android:icon="@mipmap/ic_launcher_circle" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".global.SplashActivity" android:configChanges="orientation|screenSize|uiMode" android:label="@string/app_name" android:theme="@style/SplashTheme" > <intent-filter> <action android:name="android.intent.action.MAIN" /> </intent-filter> </activity> <activity-alias android:name=".global.SplashActivity_circle" android:label="@string/app_name" android:enabled="true" android:icon="@mipmap/ic_launcher_circle" android:targetActivity=".global.SplashActivity" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity-alias> <activity-alias android:name=".global.SplashActivity_rect" android:label="@string/app_name" android:enabled="false" android:icon="@mipmap/ic_launcher_rect" android:targetActivity=".global.SplashActivity" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity-alias> <activity-alias android:name=".global.SplashActivity_square" android:label="@string/app_name" android:enabled="false" android:icon="@mipmap/ic_launcher_square" android:targetActivity=".global.SplashActivity" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity-alias> <activity android:name=".main.MainActivity" android:configChanges="orientation|screenSize|uiMode" android:label="@string/app_name" android:theme="@style/AppTheme.NoActionBar" /> </application> </manifest>
5.项目下载
链接: https://pan.baidu.com/s/1o8sqTuU 密码: tvw2