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

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

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, "点击这里切换新闻", "双击返回顶部\n再次双击刷新当前页面")
.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图示

  

  

TouTiao开源项目 分析笔记2的更多相关文章

  1. TouTiao开源项目 分析笔记6

    1.NewsChannelBean简单类笔记 1.1.Comparable接口的实现和使用 参考文章:Comparable接口的实现和使用. 因为NewsChannelBean实现了Comparabl ...

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

    1.效果预览 1.1.如下图所以,到目前为止所有的功能. 2.从InitApp开始->SplashActivity->MainActivity 2.1.InitApp源代码.这是整个项目的 ...

  3. TouTiao开源项目 分析笔记15 新闻详情之两种类型的实现

    1.预览效果 1.1.首先看一下需要实现的效果. 第一种,文字类型新闻. 第二种,图片类型新闻. 1.2.在NewsArticleTextViewBinder中设置了点击事件 RxView.click ...

  4. TouTiao开源项目 分析笔记12 从总体到局部 构建视频主页面

    1.构建视频主列表的整体碎片VideoTabLayout 1.1.首先创建一个VideoTabLayout package com.jasonjan.headnews.module.video; im ...

  5. TouTiao开源项目 分析笔记10 实现通用普通文章片段页面

    1.RxJava的Observable数据操作符总结 1.1.Map操作符 Map操作符对原始Observable发射的没一项数据应用一个你选择的函数, 然后返回一个发射这些结果的Observable ...

  6. TouTiao开源项目 分析笔记1

    1.InitApp==>项目的入口Application 1.1.继承了MultiDexApplication 超过65K方法的APP,会遇到65535的错误.原因就是为了支持比较大型的APP而 ...

  7. TouTiao开源项目 分析笔记18 视频详情页面

    1.效果预览 1.1.需要做到的真实效果 1.2.触发的点击事件 在MediaArticleVideoViewBinder的每一个item点击事件中: VideoContentActivity.lau ...

  8. TouTiao开源项目 分析笔记17 新闻媒体专栏

    1.效果预览 1.1.要实现的效果 1.2.如何调转到新闻媒体专栏 点击右上角的用户图标. 在新闻详情页面的Fragment的菜单点击事件中触发. case R.id.action_open_medi ...

  9. TouTiao开源项目 分析笔记16 新闻评论

    1.要达到的效果 1.1.主要效果图 点击了标题栏的消息图标后,然后会跳转到评论详情的页面. 1.2.触发的点击事件 在新闻详情的片段中的菜单点击事件中 设置上方标题栏的消息标的监听事件 case R ...

随机推荐

  1. [原创] Debian9上配置Samba

    Samba概述 Samba是一套使用SMB(Server Message Block)协议的应用程序,通过支持这个协议,Samba允许Linux服务器与Windows系统之间进行通信,使跨平台的互访成 ...

  2. Struts1.x 基本原理及注册模块的实现

    1.编写JavaBean:User,必须继承于ActionForm类 package myuser; import org.apache.struts.action.ActionForm; publi ...

  3. redis笔记(三)

     redis配置文件 配置文件对单位大小写不敏感 tcp-backlog  511   高并发环境连接数 tcp-keepalive   单位为秒 0 表示不会进行keepalive检测,,,建议设置 ...

  4. [转]Android中Spinner下拉列表(使用ArrayAdapter和自定义Adapter实现)

    今天学习了Spinner组件,使用Spinner相当于从下拉列表中选择项目,下面演示一下Spinner的使用(分别使用ArrayAdapter和自定义Adapter实现) (一):使用ArrayAda ...

  5. prop & attr

    <input id="chk1" type="checkbox" />是否可见 <input id="chk2" type ...

  6. ui.datepicker的回显问题

    应用场景: 页面上有一些现有的输入框,需要调用日期插件,同时还要clone一份,动态添加到页面中,动态生成的输入框在调用datepicker的时候,click事件有效,但是选择的时间无法回显到对应的输 ...

  7. Python模块与函数

    python的程序由包(package).模块(module)和函数组成.模块是处理某一类问题的集合,模块由函数和类组成,包是由一系列模块组成的集合.包必须至少包含一个__init__.py文件,该文 ...

  8. 用户表单事件(focus事件)

    以前做用户系统的时候经常用到表单验证,正则表达式事件来处理和绑定事件和进行事件,这里说的其实只是一小部分,也不是很值得写,但是今天遇到了还是写一下,毕竟基础还是蛮重要的,就算懂的童鞋,巩固一下也是好的 ...

  9. ARM实验6——ADC实验

    实验内容: 编写ADC程序,通过FS4412开发板上的电位器,改变ADC通道输入的电压值,经过ADC转换的值打印到终端. 实验目的: 熟悉开发环境: 掌握猎户座4412处理器ADC模块的使用和编程. ...

  10. 数据结构与算法分析java——线性表2(ArrarList )

    ArrayList ArrayList 是一个数组队列,相当于 动态数组.与Java中的数组相比,它的容量能动态增长.它继承于AbstractList,实现了List, RandomAccess, C ...