(一) 业务需求描述
1. 完成如下三色梯页面效果
1)自定义ViewGroup的方式完成如图一三色梯页面效果,第一条红色,第二条绿色,第三条蓝色,依次循环,台阶上显示第几条台阶数,每台阶梯子占控件宽度的1/3,垂直方向依次向下添加
2)为自定义三色梯提供添加和删除的方法,条目提供长按和点击事件
3)当点击标题栏右上方的添加按钮时,新的台阶添加到三色梯的下方,并显示添加的条数
4)长按三色梯的条目,可以删除选中条目
5)当点击添加的时候,使用属性动画,将内容平移到三色梯的条目上
6)点击条目时,将当前条目序号传到新闻列表页面
2. 完成图三所示新闻列表页面
1)使用OkHttp做网络请求,使用单例模式封装OkHttp,包括Get请求和Post请求,添加日志拦截器,自定义回调接口并回调到主线程
2)使用MVP框架搭建,分包明确,V层和M层解耦,通过接口完成V层和P层以及P层和M层通信,解决内存泄漏问题
3)使用xRecyClerView做列表展示页面,并实现下拉刷新,上拉加载更多的功能,使用ListView类的控件不得分
4)根据条目数据中的序号来实现多条目加载,每两条显示3张图片,第三条显示1张图片,依次排列,一张图片时显示在条目左侧,两条或三条时显示在条目下方,图片水平排列
5)自行选择图片加载框架完成图片加载
6)使用SQLite对新闻条目进行缓存,进入页面时,先从数据库进行读取数据展示,当有网时,从网络加载数据并更新列表数据,没有网络时,弹出吐司提示。
7)长按条目,弹出确认删除对话框,点击确认按钮时移除所选条目,添加默认的删除动画,并局部刷新
8)当确认删除后,将缓存到数据库的条目状态标记为已删除,下次从数据库读取数据时,被标记为已删除的条目不再进行展示,并且从网络请求数据时,如果加载的数据已经被删除过,则不展示该已经删除过的数据
(二) 效果图
(三) 技术选型
1. MVP;
2. OKHttp;
3. ImageLoader/Glide等
4. 接口回调;
5. RecyclerView
6. 属性动画
7. 自定义View/ViewGroup
8. Sqlite
(四) 思路分解
1. 通过文字或流程图等分析需求,形成完整解决问题思路;
2. 提供文档或流程图,一起拷贝到u盘;
(五) 接口
http://ttpc.dftoutiao.com/jsonpc/refresh?type=5010
其中,type是5010+梯子序号,比如点击的第一个台阶,则type=5011,第二个台阶,则type=5012,依次类推,当下拉刷新时,type为刚开始的值,当上拉加载更多时,type值加1
(六) 第三方依赖
OkHttp:
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
OkHttp日志拦截器:
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
xRecyclerView:
compile 'com.jcodecraeer:xrecyclerview:1.5.9'
Glide:
implementation'com.github.bumptech.glide:glide:4.7.1'
annotationProcessor'com.github.bumptech.glide:compiler:4.7.1'
ImageLoader:
素材中提供Jar包
NewsAdapter
package com.example.kson.monthdemo.adapter; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.provider.ContactsContract; import android.support.annotation.NonNull; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import com.bumptech.glide.Glide; import com.example.kson.monthdemo.MainActivity; import com.example.kson.monthdemo.R; import com.example.kson.monthdemo.bean.News; import com.example.kson.monthdemo.common.Constants; import com.google.gson.Gson; import com.jcodecraeer.xrecyclerview.XRecyclerView; import java.util.List; /** * Author:kson * E-mail:19655910@qq.com * Time:2018/05/29 * Description: */ public class NewsAdapter extends XRecyclerView.Adapter<XRecyclerView.ViewHolder> { private List<News.Data> list; private Context context; //private News news; public NewsAdapter(List<News.Data> list, Context context) { this.list = list; this.context = context; //this.news = news; } public void loadMore(List<News.Data> data) { if (list != null) { list.addAll(data); notifyDataSetChanged(); } } @NonNull @Override public XRecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { if (viewType == Constants.TYPE1) { View view = LayoutInflater.from(context).inflate(R.layout.news_item2_layout, parent, false); return new Type1ViewHolder(view); } else { View view2 = LayoutInflater.from(context).inflate(R.layout.news_item_layout, parent, false); return new Type2ViewHolder(view2); } } @Override public void onBindViewHolder(@NonNull final XRecyclerView.ViewHolder holder, int position) { holder.itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View view) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle("删除"); builder.setNegativeButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { int pos = holder.getLayoutPosition()-1;//得到下标 System.out.println("pos----"+pos); list.remove(pos);//删除集合的数据 /*news.data = list; String json = new Gson().toJson(news);*/ notifyItemRemoved(pos);//局部删除当前view并局部刷新 } }); builder.setNeutralButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { } }); builder.show(); return true; } }); News.Data data = list.get(position); if (holder instanceof Type1ViewHolder) { //1张图片 ((Type1ViewHolder) holder).title.setText(data.topic); } else if (holder instanceof Type2ViewHolder) { //三张图片 ((Type2ViewHolder) holder).title.setText(data.topic); if (data.miniimg != null && data.miniimg.size() > 0) { if (data.miniimg.size() == 1) { Glide.with(context).load(data.miniimg.get(0).src).into(((Type2ViewHolder) holder).iv1); Glide.with(context).load(data.miniimg.get(0).src).into(((Type2ViewHolder) holder).iv2); Glide.with(context).load(data.miniimg.get(0).src).into(((Type2ViewHolder) holder).iv3); } else if (data.miniimg.size() == 2) { Glide.with(context).load(data.miniimg.get(0).src).into(((Type2ViewHolder) holder).iv1); Glide.with(context).load(data.miniimg.get(1).src).into(((Type2ViewHolder) holder).iv2); Glide.with(context).load(data.miniimg.get(1).src).into(((Type2ViewHolder) holder).iv3); } else { Glide.with(context).load(data.miniimg.get(0).src).into(((Type2ViewHolder) holder).iv1); Glide.with(context).load(data.miniimg.get(1).src).into(((Type2ViewHolder) holder).iv2); Glide.with(context).load(data.miniimg.get(2).src).into(((Type2ViewHolder) holder).iv3); } } } } @Override public int getItemViewType(int position) { return position % 2 == 0 ? Constants.TYPE1 : Constants.TYPE2; } @Override public int getItemCount() { return list.size(); } class Type1ViewHolder extends XRecyclerView.ViewHolder { private TextView title; public Type1ViewHolder(View itemView) { super(itemView); title = itemView.findViewById(R.id.title1); } } class Type2ViewHolder extends XRecyclerView.ViewHolder { private TextView title; private ImageView iv1, iv2, iv3; public Type2ViewHolder(View itemView) { super(itemView); iv1 = itemView.findViewById(R.id.img1); iv2 = itemView.findViewById(R.id.img2); iv3 = itemView.findViewById(R.id.img3); title = itemView.findViewById(R.id.title3); } } }LocalNews
package com.example.kson.monthdemo.bean;
/** * Author:kson * E-mail:19655910@qq.com * Time:2018/05/30 * Description: */ public class LocalNews { public String title; public String imgurls; public String source; public String time; public boolean isDel; }
News
package com.example.kson.monthdemo.bean;
import java.util.List; /** * Author:kson