TouTiao开源项目 分析笔记4==>一个简单APP 整体常用框架

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,"点击这里切换新闻\n再次点击刷新当前页面")
                             .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()
            }
    }

}
View Code

 

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>
View Code

     

 

  @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>
View Code

  

  @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>
View Code

 

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);
        }
    }

}
View Code

 

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;
}
View Code

 

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;
    }
}
View Code

 

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
    }

}
View Code

 

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;
    }

}
View Code

 

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();
    }
}
View Code

 

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);
        }
    }
}
View Code


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);

     }
}
View Code

 

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>
View Code

 

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();
    }
}
View Code

 

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>
View Code

 

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();
    }
}
View Code

 

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>
View Code

 

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();
    }

}
View Code

 

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;
        }


}
View Code

 

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>
View Code


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>
View Code

 

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>
View Code

 

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>
View Code

 

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>
View Code

 

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>
View Code

 

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>
View Code


5.项目下载

链接: https://pan.baidu.com/s/1o8sqTuU 
密码: tvw2


posted @ 2017-12-03 12:07  Jason_Jan  阅读(1074)  评论(0编辑  收藏  举报