zoukankan      html  css  js  c++  java
  • TouTiao开源项目 分析笔记2

    1.Constant常量定义类

    1.1.源代码

    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

    1.2.作用介绍

      标签颜色存放成一个整型数组

      logo的三个不同形状,用整型数组来存放id

      图片类型用一个字符串数组来存放

      Slidable属性值用整型存放

      AS/CP,用字符串存放

      News_Channel属性,用整型存放 


    2.开源项目material-dialogs的引用

    2.1.用到了这种效果

      参考文章:开源项目material-dialogs的使用。

      

    2.2.导入引用

      compile 'com.afollestad.material-dialogs:commons:0.9.4.4'

    2.3.具体使用

      可以参考上面那篇文章。

      

      

      

      

      

      等效果,功能强大,具体代码,点击我。


    3.ActivityManager深入理解

    3.1.这里碰到了一个类ActivityManager.TaskDescription

      然后百度了一下:

      

    3.2.其他用法可以参考下面这篇文章。

      ActivityManager总结:http://blog.csdn.net/lanye11/article/details/52221359


    4.BaseActivity分析

    4.1.getWindow().setNavigationBarColor

      不知道setNavigationBarColor是什么意思

      找到了这张图。

      

    4.2.android.R.id.home

      

      就是左上角的图标,一般就是一个左箭头。

    4.3.按返回键,逐个出栈的方法

     @Override
        public void onBackPressed() {
            // Fragment 逐个出栈
            int count = getSupportFragmentManager().getBackStackEntryCount();
            if (count == 0) {
                super.onBackPressed();
            } else {
                getSupportFragmentManager().popBackStack();
            }
        }

    4.4.在清单中声明启动页活动的别名 

         <activity
                android:name=".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=".SplashActivity_circle"
                android:enabled="true"
                android:icon="@mipmap/ic_launcher_circle"
                android:label="@string/app_name"
                android:targetActivity=".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=".SplashActivity_rect"
                android:enabled="false"
                android:icon="@mipmap/ic_launcher_rect"
                android:label="@string/app_name"
                android:targetActivity=".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=".SplashActivity_square"
                android:enabled="false"
                android:icon="@mipmap/ic_launcher_square"
                android:label="@string/app_name"
                android:targetActivity=".SplashActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
            </activity-alias>

      可以看到,这里使用了<activity-alias>标签

      这里有3个标签,代表着圆形,矩形,正方形的启动页。

      所以这里每当修改了应用图标之后,这里就可以动态地变化启动图标了。

      这里有一个activity,但是写了4个<intent-filter>

      所以这招很管用。

      注意:要把第一个<intent-filter>中将<category android:name="android...LAUNCHER">删去。

      参考文章:activity-alias详解及应用。

    4.5.android禁用和开启启动图标

      这个和上面的修改应用图标结合使用。

      当修改了应用图标,应该停止当前应用的进程。

      所以要kill掉当前应用,而且桌面图标不能生效,直到应用图标修改完成,图标也换了,然后就可以点了。

     getPackageManager().setComponentEnabledSetting(new ComponentName(BaseActivity.this, getPackageName() + act),
                                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                                PackageManager.DONT_KILL_APP);

      参考文章:android禁用和开启四大组件的方法。

    4.6.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();
            initSlidrable();
        }
    
        @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 initSlidrable(){
            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


    5.MainActivity分析

    5.1.支持android材料设计,以及卡片设计模式

        implementation "com.android.support:appcompat-v7:${SUPPORT_LIBRARY_VERSION}"
        implementation "com.android.support:cardview-v7:${SUPPORT_LIBRARY_VERSION}"
        implementation "com.android.support:design:${SUPPORT_LIBRARY_VERSION}"

      在build.gradle中添加这些引用即可。

    5.2.android:fitsSystemWIndows="true"

      这个View的所有padding属性失效

      可以用于沉浸式状态栏。

      参考文章:fitsSystemWindows属性讲解。

    5.3.android:openDrawer

      这个在布局DrawerLayout中会用到。

      在布局中可以利用这个属性控制抽屉布局显示出来。

      参考文章:Android的Material Design初次尝试。

    5.4.CoordinatorLayout有什么用

      CoordinatorLayout称为“super-powered FrameLayout”基本实现两个功能:

      1.作为顶层布局

      2.调度协调子布局

      参考文章:android CoordinatorLayout使用。

    5.5.app:elevation="0dp"

      给控件,如AppBarLayout去掉阴影效果。

      参考文章:AppCompat Toolbar控件去掉阴影。

    5.6.app:layout_scrollFlags=""

      给toolbar设置混动模式

      参考文章:Android详细分析AppBarLayout。

      app:popupTheme=""

      toolbar弹出菜单样式

      参考文章:app:popupTheme作用。 

    5.7.app:layout_behavior=""

       android.support.design.widget.AppBarLayout$ScrollingViewBehavior

      这里定义了布局的行为,这是一个官方的行为

      参考这篇文章了解这个行为。

    5.8.设置底部导航栏

     <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:layout_behavior="com.meiji.toutiao.widget.behavior.BottomNavigationBehavior"
                app:menu="@menu/bottom_navigation_main" />

      这里用了官方的一个BottomNavigationView,本例中就是底部导航栏的作用。

      app:itemIconTint来设置图标点击的颜色变化。

      app:itemTextColor来设置文字点击变化。

      这里需要有定义一个样式文件==>nav_item_color_state.xml

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:color="@color/Blue_Grey" android:state_checked="true"/>
        <item android:color="@color/textColorPrimary" android:state_checked="false"/>
    </selector>

      然后还需要一个菜单布局文件:@menu/bottom_navigation_main

    <?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>

      app:showAsAction的作用就是如果就空间就显示,如果没空间就在右边的三个点中。

    5.9.左侧菜单栏

    <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"/>

      采用了NavigationView布局方式。

      左侧菜单栏的顶部利用app:headerLayout来嵌套布局。

      

    5.10.布局运行预览

                          

    5.11.如何禁用BottomNavigationView换挡模式?

      就是下方的图标是没有汉字的,如何才能图标和文字一起显示呢,写了这个类后,一行代码即可搞定。

      参考文章:

      https://stackoverflow.com/questions/40176244/how-to-disable-bottomnavigationview-shift-mode

      需要新建一个BottomNavigationView帮助类

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

      然后再调用一下这个函数即可。

     bottom_navigation = (BottomNavigationView) findViewById(R.id.bottom_navigation);
     BottomNavigationViewHelper.disableShiftMode(bottom_navigation);

    5.12.标题栏左上角引导左侧菜单栏

      五行代码即可搞定。

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

    5.13.解决toolbar.inflateMenu不生效的问题

      参考文章:http://blog.csdn.net/amd123456789/article/details/52474984

      

      其实上面只是为了测试

      真实情况还是要加,这个项目一定要重写下面这个函数,才有显示搜索图标

    @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            getMenuInflater().inflate(R.menu.menu_activity_main, menu);
            return true;
        }

    5.14.使用第三方库taptargetview

                 

      标题栏点击特效。

      参考文章:安卓taptargetview。

      高亮功能提示效果。

      implementation 'com.getkeepsafe.taptargetview:taptargetview:1.9.1'

    5.15.利用TapTarget设置引导用户页面  

    private void showTapTarget() {
            final Display display = getWindowManager().getDefaultDisplay();
            final Rect target = new Rect(
                    0,
                    display.getHeight(),
                    0,
                    display.getHeight());
            target.offset(display.getWidth() / 8, -56);
    
            // 引导用户使用
            TapTargetSequence sequence = new 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(new TapTargetSequence.Listener() {
                        @Override
                        public void onSequenceFinish() {
                            SettingUtil.getInstance().setIsFirstTime(false);
                        }
    
                        @Override
                        public void onSequenceStep(TapTarget lastTarget, boolean targetClicked) {
    
                        }
    
                        @Override
                        public void onSequenceCanceled(TapTarget lastTarget) {
                            SettingUtil.getInstance().setIsFirstTime(false);
                        }
                    });
            sequence.start();
        }

     5.16.横竖屏切换保存数据==>重写onSaveInstanceState

     @Override
        protected void onSaveInstanceState(Bundle outState) {
            // recreate 时记录当前位置 (在 Manifest 已禁止 Activity 旋转,所以旋转屏幕并不会执行以下代码)
            outState.putInt(POSITION, position);
            outState.putInt(SELECT_ITEM, bottom_navigation.getSelectedItemId());
        }


    6.目前效果

    6.1.创建好了SplashActivity+MainActivity

      但是具体的Fragment一个都还没有实现。

      实现了一个左侧菜单+顶部标题栏+底部导航栏

    6.2.GIF图示

      

      



    既然选择了,便不顾风雨兼程。Just follow yourself.
  • 相关阅读:
    紧急项目处理方法(转)
    最佳窗体间传送数据的方法,同时可适用于其他传值方式
    一周七句
    电子书下载:Beginning Silverlight 5 in C# 4th
    ERP专业词汇集合
    电子书下载:CRM Fundamentals
    电子书下载:Programming Entity Framework DbContext
    电子书下载:Data Mining Techniques in CRM
    C#+.Net使用RemObjects建立客户端服务端
    1033,2052 是什么意思?
  • 原文地址:https://www.cnblogs.com/Jason-Jan/p/7940664.html
Copyright © 2011-2022 走看看