版权声明:欢迎分享,但请注明出处,谢谢 https://blog.csdn.net/qq_28057577/article/details/78226084
前言:
在
Android实战(橘子娱乐)-首页(第一篇 MVP框架基本搭建和实现准备) 中,我们实现了首页实现的准备以及MVP框架的基本搭建,也提到这篇我们将对首页的布局和activiy代码进行讲解,接下来我们完成这部分的学习。
依然是一张gif图直观些:
ok,讲布局xml之前我们先来设置一下Activity的Theme,下面是Theme代码(styles.xml):
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimary</item>
<item name="colorAccent">@color/colorPrimary</item>
<item name="android:windowBackground">@color/background_material_light_new</item>
<item name="android:windowAnimationStyle">@style/AnimationActivity</item>
<!-- ActionBar上Menu的字体颜色 -->
<item name="actionMenuTextColor">@color/white</item>
<item name="android:actionOverflowMenuStyle" tools:targetApi="lollipop">@style/OverflowMenu</item>
<!--按钮的颜色-->
<item name="drawerArrowStyle">@style/AppTheme.DrawerArrowToggle</item>
</style>
<style name="AppTheme.DrawerArrowToggle" parent="Base.Widget.AppCompat.DrawerArrowToggle">
<item name="color">@android:color/white</item>
</style>
- <style name="OverflowMenu" parent="Widget.AppCompat.PopupMenu.Overflow">
<item name="overlapAnchor">false</item>
<item name="android:color">@color/white</item>
</style>
<!--Activity动画-->
<style name="AnimationActivity" parent="@android:style/Animation.Activity">
<!--打开新activity的进入效果-->
<item name="android:activityOpenEnterAnimation">@anim/slide_in_left</item>
<!--打开新activity销毁前的效果-->
<item name="android:activityOpenExitAnimation">@anim/slide_out_left</item>
<!--关闭当前activity,进入上一activity的效果-->
<item name="android:activityCloseEnterAnimation">@anim/slide_in_right</item>
<!--当前activity关闭的效果-->
<item name="android:activityCloseExitAnimation">@anim/slide_out_right</item>
</style>
</resources>
这么多style其实我重点想说一下
android:windowAnimationStyle 也就是设置Activity进入退出切换的动画效果,上面注释很清楚
<!--打开新activity的进入效果-->
<item name="android:activityOpenEnterAnimation">@anim/slide_in_left</item>
<!--打开新activity销毁前的效果-->
<item name="android:activityOpenExitAnimation">@anim/slide_out_left</item>
<!--关闭当前activity,进入上一activity的效果-->
<item name="android:activityCloseEnterAnimation">@anim/slide_in_right</item>
<!--当前activity关闭的效果-->
<item name="android:activityCloseExitAnimation">@anim/slide_out_right</item>
那我们具体来看一下每个动画效果应该是怎样写的;
首先在res下面建anim文件夹保存动画文件,再来看具体文件:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromXDelta="0"
android:toXDelta="100%"
/>
<!--
//间隔时间 单位为毫秒
android:duration="300"
//起始时x坐标的位置,其他类推
android:fromXDelta="0"
//加P表示一父view为参照物
android:toXDelta="100%p"
-->
</set>
注释一看便懂,也就不赘述了,如果不是很明白可以修改着跑起来看他们的效果就明白了。其实除了这种在styles.xml文件夹中添加style添加activity过渡效果以外,Google其实还提供了一种叫 ActvityOptions的一种方式添加过渡效果,想了解的伙伴可以去搜一下,这里就不展开了。
style文件定义好我们需要用,这时候直接在AndroidManifest.xml的application标签下设置
Android:theme="@style/AppTheme"应用于全局即可,当然你可以设置单个Activity。
style设置好接下来我们来看首页布局文件(actvity_main.xml):
<?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"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<!--主布局-->
<!--
CoordinatorLayout是一个super FrameLayout他提供了不需要写动画效果就能实现滚动效果的一种能力
比如:让浮动按钮上下滑动显示Snackbar,扩展或者缩小toolbar头部,控制某个view收缩扩展。
-->
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/rg_root">
<!--
AppBarLayout是继承自LinearLayout实现的一个ViewGroup容器组件,作用是支持了
APP Bar的手势滑动操作
-->
<android.support.design.widget.AppBarLayout
style="@style/Theme.AppCompat.Light"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp">
<!--顶部导航栏
layout_scrollFlags监听IRecyclerView的滚动事件
必须至少启用scroll ,enterAlways表示一旦滚动这个view就可见
app:popupTheme:设置有上角弹出菜单的样式
-->
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:titleTextAppearance="@style/Toolbar.TitleText"
app:popupTheme="@style/AppTheme.PopupOverlay">
<RelativeLayout
android:padding="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:text="首页"
android:textSize="16sp"
android:textColor="@color/white"
android:layout_width="wrap_content"
android:layout_centerVertical="true"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
/>
<ImageView
android:id="@+id/btn_message"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="10dp"
android:clickable="true"
android:src="@drawable/home_message"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
</RelativeLayout>
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<com.aspsine.irecyclerview.IRecyclerView
android:id="@+id/rv_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:refreshHeaderLayout="@layout/irecyclerview_refresh_header"
app:refreshEnabled="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
</com.aspsine.irecyclerview.IRecyclerView>
</android.support.design.widget.CoordinatorLayout>
<!--侧滑菜单配置
app:headerLayout:配置侧滑抽屉顶部布局
app:menu:配置底部菜单
-->
<android.support.design.widget.NavigationView
android:id="@+id/navigation"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="@color/white"
app:headerLayout="@layout/drawer_head_view"
app:menu="@menu/drawer_menu"/>
</android.support.v4.widget.DrawerLayout>
分析:DrawerLayout和Navigation这里就不讲了,这里主要分析一下,在RecyclerView上滑的过程中,Toolbar更随滚动隐藏和展示的效果实现。要支持Toolbar
隐藏和展示
的效果需要
将内容保存到CoordinatorLayout
这个FrameLayout中,然后需要Toolbar和RecyclerView绑定起来,这样在RecyclerView滑动的时候才会触发Toolbar的显示与隐藏。所以上面在Toolbar中设置了
a
pp:layout_scrollFlags
=
"scroll|enterAlways"
,在IRecyclerView上设置了
app:layout_behavior
=
"@string/appbar_scrolling_view_behavior"
就是这个意图。
app:layout_behavior
=
"@string/appbar_scrolling_view_behavior"
是固定不变的,我们来分析一下
a
pp:layout_scrollFlags
=
"scroll|enterAlways"
的值和区别:
app:refreshHeaderLayout="@layout/irecyclerview_refresh_header"
app:refreshEnabled="true"
一个是设置支持刷新,另外一个是设置刷新头部布局的,看上面gif下拉刷新的时候有几种状态:1.刷新前显示释放刷新 2.刷新中显示正在刷新 3.刷新完成后显示刷新完成。我们来看看他具体是什么
(irecyclerview_refresh_header.xml)
<?xml version="1.0" encoding="utf-8"?>
<com.andy.orange.widget.ClassicRefreshHeaderView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="60dp">
</com.andy.orange.widget.ClassicRefreshHeaderView>
一个自定义的刷新头,这节我们先不讲,放到第三篇来完成。接下来我们来看看主页面Java类的逻辑代码:
MainActivity.java
package com.andy.orange.ui;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.andy.orange.R;
import com.andy.orange.adapter.MainRecyclerViewAdapter;
import com.andy.orange.anims.LandingAnimator;
import com.andy.orange.anims.ScaleInAnimationAdapter;
import com.andy.orange.base.BaseActivity;
import com.andy.orange.bean.Film;
import com.andy.orange.ui.coder.CoderActivity;
import com.andy.orange.ui.home.presenter.impl.MainPresenterImpl;
import com.andy.orange.ui.home.view.MainView;
import com.andy.orange.ui.movie.MovieDetailActivity;
import com.andy.orange.ui.movie.MovieDisplayActivity;
import com.andy.orange.ui.music.MusicActivity;
import com.andy.orange.utils.SharedPreferencesUtils;
import com.aspsine.irecyclerview.IRecyclerView;
import com.aspsine.irecyclerview.OnRefreshListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import butterknife.BindView;
/**
* Created by Andy Lau on 2017/8/8.
*/
public class MainActivity extends BaseActivity implements MainView,
NavigationView.OnNavigationItemSelectedListener,OnRefreshListener,View.OnClickListener{
private int count=24;
private int start=0;
private int randomStart= new Random().nextInt(300);
@BindView(R.id.toolbar)
Toolbar mToolbar;
@BindView(R.id.navigation)
NavigationView mNavigation;
@BindView(R.id.drawer_layout)
DrawerLayout mDrawerLayout;
@BindView(R.id.rv_content)
IRecyclerView mIRecyclerView;
@BindView(R.id.btn_message)
ImageView mMsgBtn;
private ImageView IvHeadImg;
private TextView loginTv;
private MainRecyclerViewAdapter mMainAdapter;
private List<Film.SubjectsBean> mList = new ArrayList<>();
private MainPresenterImpl mainPresenter;
/*
* 侧滑导航的选中监听
* */
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
//侧滑导航选中事件监听
int itemId=item.getItemId();
switch (itemId){
case R.id.menu_home:
break;
case R.id.menu_live:
//启动直播页面
Intent liveIntent=new Intent(MainActivity.this,LiveActivity.class);
startActivity(liveIntent);
break;
case R.id.menu_duanzi:
//启动搞笑段子页面
Intent duanIntent=new Intent(MainActivity.this,DuanziActivity.class);
startActivity(duanIntent);
break;
case R.id.menu_book:
//启动搞笑段子页面
Intent bookIntent=new Intent(MainActivity.this,BookActivity.class);
startActivity(bookIntent);
break;
case R.id.menu_movie:
//启动电影页面
Intent intent = new Intent(MainActivity.this, MovieDisplayActivity.class);
startActivity(intent);
break;
case R.id.menu_music:
//启动音乐页面
Intent intent1=new Intent(MainActivity.this, MusicActivity.class);
startActivity(intent1);
break;
case R.id.menu_info:
//启动作者信息页
Intent coderIntent=new Intent(MainActivity.this, CoderActivity.class);
startActivity(coderIntent);
break;
case R.id.menu_about:
//启动开源信息
break;
case R.id.menu_logout:
//退出
SharedPreferencesUtils.setSharedData(this,"is_login",false,"boolean");
Intent restart=new Intent(MainActivity.this, MainActivity.class);
startActivity(restart);
break;
}
//关闭drawer
item.setChecked(true);
mDrawerLayout.closeDrawer(GravityCompat.START);
return true;
}
/*
* 继承自封装的BaseActivity
* */
@Override
public int getChildLayoutId() {
return R.layout.activity_main;
}
@Override
public void initPresenter() {
mainPresenter=new MainPresenterImpl(this, this);
}
@Override
public void initView() {
mContext=this;
setToolbar();
setNavigationView();
initData();
mainPresenter.requestHotFilm(randomStart,count);
randomStart=randomStart+count;
}
/*
* 设置toolbar和与drawerLayout绑定
* */
private void setToolbar() {
setSupportActionBar(mToolbar);
ActionBar actionBar=getSupportActionBar();
//菜单按钮可用
actionBar.setHomeButtonEnabled(true);
//回退按钮可用
//actionBar.setDisplayHomeAsUpEnabled(true);
//将drawerLayout和toolbar绑定在一起
ActionBarDrawerToggle toggle=new ActionBarDrawerToggle(this,mDrawerLayout,mToolbar,R.string.app_name,R.string.app_name);
//初始化状态
toggle.syncState();
//设置drawerLayout的监听事件 打开/关闭
mDrawerLayout.addDrawerListener(toggle);
//去除侧滑菜单的遮罩层
//mDrawerLayout.setScrimColor(Color.TRANSPARENT);
//初始化内容
// mToolbar.setTitleTextColor(getResources().getColor(R.color.black));
//设置右上角消息图标监听事件
mMsgBtn.setOnClickListener(this);
}
/*
* 设置导航菜单
* */
private void setNavigationView() {
//设置图标显示他自己的颜色
mNavigation.setItemIconTintList(null);
//获取到侧滑菜单顶部
View headerView=mNavigation.getHeaderView(0);
//获取绑定头像和登录提示文本
IvHeadImg= (ImageView) headerView.findViewById(R.id.header_icon);
loginTv= (TextView) headerView.findViewById(R.id.nick_name);
//设置导航监听
mNavigation.setNavigationItemSelectedListener(this);
setHomeDefaultState();
//初始化登录状态
initLoginState();
}
/**
* 设置首页默认被选中的状态
*/
private void setHomeDefaultState(){
Menu menu=mNavigation.getMenu();
MenuItem item=menu.getItem(0).getSubMenu().getItem(0);
item.setChecked(true);
}
/*
* 初始化登录状态
* */
private void initLoginState() {
//获取sharedPreference的登录状态
Boolean isLogin=false;
isLogin= (Boolean) SharedPreferencesUtils.readSharedData(mContext,"is_login","boolean");
if (null !=isLogin && isLogin){
//获取上次登录时间
long date= (long) SharedPreferencesUtils.readSharedData(this,"login_date","long");
//大于一周设置设置登录状态为false
if (System.currentTimeMillis()-date>7*24*3600*1000){
SharedPreferencesUtils.setSharedData(this,"is_login",false,"boolean");
isLogin=false;
}
}
if (null !=isLogin && isLogin){
IvHeadImg.setImageResource(R.mipmap.head_image);
String username= (String) SharedPreferencesUtils.readSharedData(mContext,"nick_name","string");
loginTv.setText(username);
}else {
//Toast.makeText(mContext,"未等录 " ,Toast.LENGTH_SHORT).show();
loginTv.setText("点击登录");
IvHeadImg.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//启动登录界面
Intent intent=new Intent(MainActivity.this,LoginActivity.class);
startActivity(intent);
//Toast.makeText(MainActivity.this,"login",Toast.LENGTH_SHORT).show();
}
});
}
}
/*
* 初始化数据
* */
private void initData() {
//初始化适配器
mMainAdapter = new MainRecyclerViewAdapter(mContext, mList);
//设置布局
GridLayoutManager manager=new GridLayoutManager(mContext,2,GridLayoutManager.VERTICAL,false);
//设置item跨度
manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
if (position==0||position==1||position==mList.size()+2){
return 2;
}
return 1;
}
});
//绑定布局管理器和刷新监听器
mIRecyclerView.setLayoutManager(manager);
mIRecyclerView.setOnRefreshListener(this);
//MainRecyclerViewAdapter开放setOnItemClickListener()方法
mMainAdapter.setOnItemClickListener(new MainRecyclerViewAdapter.onItemClickListener() {
@Override
public void onItemClick(int position, ImageView imageView) {
//启动电影细节页
Intent intent=new Intent(MainActivity.this, MovieDetailActivity.class);
intent.putExtra("movieId",mList.get(position).getId());
startActivity(intent);
}
});
//设置recyclerview动画
mIRecyclerView.setItemAnimator(new LandingAnimator());
//设置适配器
mIRecyclerView.setIAdapter(new ScaleInAnimationAdapter(mMainAdapter));
}
@Override
public void onRefresh() {
mIRecyclerView.setRefreshing(true);
mainPresenter.requestHotFilm(randomStart,count);
randomStart=randomStart+count;
}
/*
* 继承自MainRecyclerViewAdapter.OnItemClickListener接口的方法
* */
@Override
public void getFilmInfos(Film film) {
mIRecyclerView.setRefreshing(false);
for (int i=0;i<film.getSubjects().size();i++) {
mList.add(film.getSubjects().get(i));
}
mMainAdapter.notifyDataSetChanged();
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_message:
Toast.makeText(mContext,"查看推送消息!",Toast.LENGTH_LONG).show();
Log.d("log","查看推送消息");
break;
default:
break;
}
}
}
这部分的代码有点多,具体的注释都很清楚,我们主要理一理思路,先来继承关系
class MainActivity extends BaseActivity implements MainView,
NavigationView.OnNavigationItemSelectedListener,OnRefreshListener,View.OnClickListener
首先继承了我们之前写好的基础activity类,继承了一些通用的设置和需要实现的方法,然后继承了还未见过真面目的MainView,将MainActivity设置为MainView的子类方便后面presenter传递获取的数据并显示,最后是继承的一些监听接口这里就不过多赘述了。然后整个架子过程就是:显示布局——>初始化presenter——>初始化view和数据(根据SharedPreferences保存的登录状态初始化navigation header的显示内容,未登录显示未登录状态点击进行登录,已登录显示账号和头像——>通过presenter加载数据——>加载数据完成后在继承MainView的
getFilmInfos
(
Film
film
)
的方法中实现添加内容到原有的list然后通知IRecyclerView刷新。)
这篇就学习到这里,在首页中我们还有
MainView接口、
SharedPreferencesUtils、
MainPresenter
、
MainRecyclerViewAdapter
没有完成,我们将在后面一步步的进行学习完成,下面贴出侧边栏导航的代码,方便学习
drawer_menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item android:id="@+id/hobby"
android:title="音乐与电影">
<menu>
<item android:title="首页" android:id="@+id/menu_home" android:icon="@drawable/menu_index"/>
<item android:title="直播" android:id="@+id/menu_live" android:icon="@drawable/menu_live"/>
<item android:title="搞笑段子" android:id="@+id/menu_duanzi" android:icon="@drawable/menu_funny"/>
<item android:title="书城" android:id="@+id/menu_book" android:icon="@drawable/menu_book"/>
<item android:title="电影" android:id="@+id/menu_movie" android:icon="@drawable/menu_film"/>
<item android:title="音乐" android:id="@+id/menu_music" android:icon="@drawable/menu_music"/>
</menu>
</item>
</group>
<group android:checkableBehavior="single">
<item android:id="@+id/more"
android:title="更多">
<menu>
<item android:title="作者信息" android:id="@+id/menu_info" android:icon="@drawable/menu_coder"/>
<item android:id="@+id/menu_about"
android:icon="@drawable/menu_copyright"
android:title="开源信息"/>
<item android:id="@+id/menu_logout"
android:icon="@drawable/menu_out"
android:title="退出"/>
</menu>
</item>
</group>
</menu>