我们先来看看效果
富文本和发帖,回帖,帖子界面我都没实现,我的实现内容是整体的效果,比如鱼吧的悬浮按钮效果等等
1.在mainfests的设置MainActivity为NoActionBar主题,这样我们就可以设置我们自己的toolbar了
<activity
android:name=".MainActivity"
android:theme="@style/Theme.Design.Light.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
添加依赖
compile ‘com.scwang.smartrefresh:SmartRefreshLayout:1.1.0-alpha-24’
compile ‘com.scwang.smartrefresh:SmartRefreshHeader:1.1.0-alpha-24’
//没有使用特殊Header,可以不加这行
implementation ‘com.android.support:design:28.0.0’
implementation ‘com.android.support:recyclerview-v7:28.0.0’
compile ‘com.flyco.tablayout:FlycoTabLayout_Lib:2.1.2@aar’
implementation ‘com.android.support:support-v4:28.0.0’
compile ‘com.android.support.constraint:constraint-layout:1.0.2’
implementation ‘com.android.support:support-v4:28.0.0’
implementation ‘com.android.support:cardview-v7:28.0.0’
//注解bind
compile ‘com.jakewharton:butterknife:8.8.1’
annotationProcessor ‘com.jakewharton:butterknife-compiler:8.8.1’
compile ‘com.github.clans:fab:1.6.4’
implementation ‘org.greenrobot:eventbus:3.1.1’
mainActivity是我们的首页,在它的activity_main.xml中
<?xml version="1.0" encoding="utf-8"?>
<com.scwang.smartrefresh.layout.SmartRefreshLayout 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"
tools:context=".MainActivity">
<com.scwang.smartrefresh.layout.header.ClassicsHeader
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.CollapsingToolbarLayout
android:fitsSystemWindows="true"
android:layout_width="match_parent"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_marginTop="75dp"
app:layout_collapseMode="parallax"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:src="@drawable/baoge"
android:scaleType="fitXY"
android:layout_width="match_parent"
android:layout_height="90dp"/>
</RelativeLayout>
<android.support.v7.widget.Toolbar
android:id="@+id/main_activity_toorbar"
android:layout_width="match_parent"
android:layout_height="68dp"
android:background="#fff"
app:layout_collapseMode="pin">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:id="@+id/system_bar_view"
android:layout_width="match_parent"
android:layout_height="20dp"/>
<TextView
android:id="@+id/tv1"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_below="@id/system_bar_view"
android:layout_marginTop="10dp"
android:background="@drawable/find_tab_btn_return"/>
<TextView
android:id="@+id/tv2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="4dp"
android:layout_marginTop="10dp"
android:layout_below="@id/system_bar_view"
android:layout_centerHorizontal="true"
android:textColor="#000"
android:textSize="16sp"
android:gravity="center"
android:text="个人中心"/>
</RelativeLayout>
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
<android.support.design.widget.TabLayout
app:tabIndicatorColor="#FFFF8940"
android:id="@+id/tab_layout"
app:tabIndicatorFullWidth="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#fff"/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/tab_layout_vp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>
<com.scwang.smartrefresh.layout.footer.ClassicsFooter
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</com.scwang.smartrefresh.layout.SmartRefreshLayout>
关于CollapsingToolbarLayout使用的部分,请自行百度,SmartRefreshLayout是用于刷新的控件,在mainActivity中
public class MainActivity extends AppCompatActivity {
private Toolbar main_activity_toorbar;
private TabLayout tab_layout;
private ViewPager tab_layout_vp;
private List<Fragment>tieZiFragmentList;
private ViewPagerAdapter viewPagerAdapter;
private AppBarLayout appbar;
//帖子标题
private String title[]={"看帖","精华","主播","视频","相册"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
setContentView(R.layout.activity_main);
main_activity_toorbar=findViewById(R.id.main_activity_toorbar);
tab_layout=findViewById(R.id.tab_layout);
tab_layout_vp=findViewById(R.id.tab_layout_vp);
appbar=findViewById(R.id.appbar);
setSupportActionBar(main_activity_toorbar);
tieZiFragmentList=new ArrayList<>();
Bundle bundle=new Bundle();
tieZiFragmentList.add(TieZiFragment.getInstance("1"));
tieZiFragmentList.add(TieZiFragment.getInstance("2"));
tieZiFragmentList.add(TieZiFragment.getInstance("3"));
tieZiFragmentList.add(TieZiFragment.getInstance("2"));
tieZiFragmentList.add(TieZiFragment.getInstance("2"));
viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(),tieZiFragmentList,title);
tab_layout_vp.setAdapter(viewPagerAdapter);
tab_layout_vp.setOffscreenPageLimit(1);
tab_layout.setTabIndicatorFullWidth(false);
tab_layout.setupWithViewPager(tab_layout_vp);
tab_layout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
Log.i("msg11",tab.getPosition()+"");
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
2.新建TieZiFragment用于展示ViewPager中的内容
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical"
android:id="@+id/re"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".TieZiFragment">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:descendantFocusability="blocksDescendants">
<android.support.v7.widget.RecyclerView
android:id="@+id/show_tiezi_rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="6dp"/>
</RelativeLayout>
<com.github.clans.fab.FloatingActionButton
android:id="@+id/send_posts"
android:layout_alignParentBottom="true"
android:layout_width="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginBottom="15dp"
android:layout_marginRight="40dp"
android:layout_height="wrap_content"
app:fab_colorNormal="#FFF1CF3A"
android:src="@drawable/send_topic"></com.github.clans.fab.FloatingActionButton>
</RelativeLayout>
public class TieZiFragment extends Fragment {
public String title;
private List<String>stringList;
public RecyclerView show_tiezi_rv;
private RvAdapter rvAdapter;
private TextView tv;
//按钮下滑距离
private int marBottomFab;
//按钮下滑动画集合
private AnimatorSet animatorSet;
//按钮上升动画集合
private AnimatorSet animatorSet2;
private RelativeLayout re;
//按钮的状态,true是显示,flase是隐藏
private boolean isFabShow;
private FloatingActionButton send_posts;
public void setTitle(String title) {
this.title = title;
}
public static TieZiFragment getInstance(String titl1e){
TieZiFragment tieZiFragment=new TieZiFragment();
tieZiFragment.setTitle(titl1e);
return tieZiFragment;
}
public TieZiFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v= inflater.inflate(R.layout.fragment_tie_zi, container, false);
show_tiezi_rv=v.findViewById(R.id.show_tiezi_rv);
send_posts=v.findViewById(R.id.send_posts);
isFabShow=true;
re=v.findViewById(R.id.re);
marBottomFab=DensityUtil.dip2px(getContext(),80);
stringList=new ArrayList<>();
if (title.equals("1"))
for (int i=0;i<100;i++){
stringList.add("this is the"+i+"item");
}
if (title.equals("2"))
for (int i=0;i<120;i++){
stringList.add("this is the"+i+"item");
}
if (title.equals("3"))
for (int i=0;i<5;i++){
stringList.add("this is the"+i+"item");
}
//数据加载完毕时,add null,用于显示提示
stringList.add(null);
show_tiezi_rv.setLayoutManager(new LinearLayoutManager(getContext()));
rvAdapter=new RvAdapter(stringList);
show_tiezi_rv.setAdapter(rvAdapter);
rvAdapter.setRecyclerViewWeakReference(new WeakReference<RecyclerView>(show_tiezi_rv));
rvAdapter.setRecviewOnclickDao(new RecviewOnclickDao() {
@Override
public void recviewOnclickMethod(Integer id, String... params) {
Intent intent=new Intent(getActivity(),PostsActivity.class);
startActivity(intent);
}
});
initAnimation();
show_tiezi_rv.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (dy>0){//下滑时
if (isFabShow) {
isFabShow = false;
isRunningAnimation();
animatorSet.start();
}
}else {
if (!isFabShow) {
isFabShow = true;
animatorSet2.start();
}
}
}
});
// int height=(MyApplication.screenHeight-MainActivity.appBarheight)/5;
// Log.i("msg",height+"");
// send_posts.setTranslationY(-height);
return v;
}
public void initAnimation(){
animatorSet=new AnimatorSet();
animatorSet.setInterpolator(new AccelerateInterpolator());
animatorSet2=new AnimatorSet();
animatorSet2.setInterpolator(new AccelerateInterpolator());
ObjectAnimator objectAnimator=ObjectAnimator.ofFloat(send_posts,"TranslationY",0,marBottomFab);
ObjectAnimator objectAnimator2=ObjectAnimator.ofFloat(send_posts,"TranslationY",0,-marBottomFab);
animatorSet.play(objectAnimator);
animatorSet.setDuration(200);
animatorSet2.play(objectAnimator2);
animatorSet2.setDuration(200);
}
@Override
public void onDestroy() {
super.onDestroy();
//停止动画,防止泄露
isRunningAnimation();
}
//停止动画
public void isRunningAnimation(){
if (animatorSet.isRunning()){
animatorSet.cancel();
}
if (animatorSet2.isRunning()){
animatorSet2.cancel();
}
}
}
3.新建PostsActivity用于展示第二部分内容
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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"
tools:context=".PostsActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.CollapsingToolbarLayout
android:fitsSystemWindows="true"
android:layout_width="match_parent"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_marginTop="75dp"
app:layout_collapseMode="parallax"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:text="这里是富文本帖子内容"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="120dp" />
</RelativeLayout>
<android.support.v7.widget.Toolbar
android:id="@+id/posts_activity_toorbar"
android:layout_width="match_parent"
android:layout_height="68dp"
android:background="#fff"
app:layout_collapseMode="pin">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:id="@+id/system_bar_view"
android:layout_width="match_parent"
android:layout_height="20dp"/>
<TextView
android:id="@+id/tv1"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_below="@id/system_bar_view"
android:layout_marginTop="10dp"
android:background="@drawable/find_tab_btn_return"/>
<TextView
android:id="@+id/tv2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="4dp"
android:layout_marginTop="10dp"
android:layout_below="@id/system_bar_view"
android:layout_centerHorizontal="true"
android:textColor="#000"
android:textSize="16sp"
android:gravity="center"
android:text="个人中心"/>
</RelativeLayout>
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
<android.support.design.widget.TabLayout
app:tabIndicatorColor="#FFFF8940"
android:id="@+id/posts_tab_layout"
app:tabIndicatorFullWidth="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#fff"/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/posts_tab_vp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>
public class PostsActivity extends AppCompatActivity {
@BindView(R.id.posts_activity_toorbar)
android.support.v7.widget.Toolbar posts_activity_toorbar;
@BindView(R.id.posts_tab_vp)
ViewPager posts_tab_vp;
@BindView(R.id.posts_tab_layout)
TabLayout posts_tab_layout;
private List<Fragment> tieZiFragmentList;
private ViewPagerAdapter viewPagerAdapter;
private String title[]={"评论","楼主评论"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_posts);
ButterKnife.bind(this);
setSupportActionBar(posts_activity_toorbar);
tieZiFragmentList=new ArrayList<>();
tieZiFragmentList.add(TieZiFragment.getInstance("2"));
tieZiFragmentList.add(TieZiFragment.getInstance("3"));
viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(),tieZiFragmentList,title);
posts_tab_vp.setAdapter(viewPagerAdapter);
posts_tab_vp.setOffscreenPageLimit(1);
posts_tab_layout.setTabIndicatorFullWidth(false);
posts_tab_layout.setupWithViewPager(posts_tab_vp);
}
}
4.新建RvAdapter类,作为recycleview的适配器
public class RvAdapter extends RecyclerView.Adapter {
private List<String>stringList;
private RecviewOnclickDao recviewOnclickDao;
//不为空时
private final int NOT_NULL_ITEM=1;
//数据加载完毕
private final int NULL_ITEM=0;
private WeakReference<RecyclerView>recyclerViewWeakReference;
public RvAdapter(List<String> stringList) {
this.stringList = stringList;
}
public void setRecyclerViewWeakReference(WeakReference<RecyclerView> recyclerViewWeakReference) {
this.recyclerViewWeakReference = recyclerViewWeakReference;
}
public class RvAdapterViewHolder extends RecyclerView.ViewHolder{
public TextView list_item_tv;
public RvAdapterViewHolder(@NonNull View itemView) {
super(itemView);
list_item_tv=itemView.findViewById(R.id.list_item_tv);
}
}
public class NullRvViewHolder extends RecyclerView.ViewHolder{
public NullRvViewHolder(@NonNull View itemView) {
super(itemView);
}
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
if (i==NOT_NULL_ITEM)
return new RvAdapterViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item,viewGroup,false));
else if (i==NULL_ITEM)
return new NullRvViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.rv_null_item,viewGroup,false));
return null;
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
if (viewHolder instanceof RvAdapterViewHolder) {
RvAdapterViewHolder rvAdapterViewHolder = (RvAdapterViewHolder) viewHolder;
rvAdapterViewHolder.list_item_tv.setText(stringList.get(i));
rvAdapterViewHolder.list_item_tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
recviewOnclickDao.recviewOnclickMethod(0, "0");
}
});
}
}
@Override
public int getItemViewType(int position) {
if (stringList.get(position)!=null)
return NOT_NULL_ITEM;
else
return NULL_ITEM;
}
@Override
public int getItemCount() {
return stringList.size();
}
public void setRecviewOnclickDao(RecviewOnclickDao recviewOnclickDao) {
this.recviewOnclickDao = recviewOnclickDao;
}
}
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/list_item_tv"
android:text="1111"
android:padding="10dp"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
rv_null_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:layout_marginTop="10dp"
android:gravity="center"
android:text="已经没有更多数据"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
5.新建MyApplication
<application
//引用新建的application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:theme="@style/Theme.Design.Light.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".PostsActivity"
android:theme="@style/Theme.Design.Light.NoActionBar"></activity>
</application>
public class MyApplication extends Application {
//屏幕高度
public static int screenHeight;
//屏幕宽度
public static int screenWidth;
@Override
public void onCreate() {
super.onCreate();
WindowManager wm = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
screenHeight= wm.getDefaultDisplay().getHeight();
screenWidth = wm.getDefaultDisplay().getWidth();
}
}
6.新建java类DensityUtil用于放一些公用的函数
public class DensityUtil {
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp
*/
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
}