这是第一篇博客,就是为了记住写这个小demo的所得所感。
demo涉及到:glide、recyclerview、gson和json等。
下面直接上代码:
先做好准备工作,那就是导入依赖包,资源文件就不上传了,纯粹是因为懒
compile 'com.android.support:design:26.+'
compile 'com.android.support:recyclerview-v7:26.+'
compile 'com.android.support:cardview-v7:26.+'
compile 'com.github.bumptech.glide:glide:4.0.0'
compile 'com.google.code.gson:gson:2.8.1'
compile 'com.squareup.okhttp3:okhttp:3.9.0'```
一.SplashActivity--启动活动,也即欢迎界面
使用handler实现延时跳转到指定活动,通过获取在MeiziActivity和ZhihuNewsActivity中存储的SharedPreferences值来获取上次应用退出时所在活动,以实现简陋的历史记录功能。这个活动对应的xml文件随便弄就行了。
> new Handler().postDelayed(new Runnable() {
@Override
public void run() {
SharedPreferences preferences = getSharedPreferences("ActivityRecord", 0);
int record = preferences.getInt("activity", 0);
if (record == 0) {
Intent intent = new Intent(SplashActivity.this, MeiziActivity.class);
startActivity(intent);
} else {
Intent intent = new Intent(SplashActivity.this, ZhihuNewsActivity.class);
startActivity(intent);
}
finish();
}
}, 3000);
二.MeiziActivity,模仿简书上一篇文章写的这个活动。[原文传送门](http://www.jianshu.com/p/12ec590f6c76)
1.首先是xml布局,最外层使用DrawerLayout,这是一个抽屉布局,可以包含两个直接子控件,依次为主屏幕布局和滑动菜单布局。
` <android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:fitsSystemWindows="true">
<android.support.v7.widget.Toolbar
android:id="@+id/toolBar_meizi"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView_meizi"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
`
抽屉布局要注意滑动菜单的方向,这里是`android:layout_gravity="start"`
在主屏幕布局里,最外层是CoordinatorLayout,这是一个类似framelayout的布局方式,可以监听子控件的各种事件,自动做出最合理的响应。接着是AppBarLayout,使用这个控件可以使toolbar不至于被RecyclerView给挡住。再在AppBarLayout里面使用toolbar即可。这就是主页面的布局。头部弄好了,下面主体部分就是一个简单的RecyclerView。对于滑动菜单,我这里将其单独作为一个布局存在,便于复用。`<include layout="@layout/navigationview" />`
2.看代码以及注释。
package com.spring_ballet.looklook;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
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.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.MenuItem;
import android.widget.Toast;
import com.google.gson.Gson;
import com.spring_ballet.looklook.Adapter.ZhiHuNewsAdapter;
import com.spring_ballet.looklook.bean.Story;
import com.spring_ballet.looklook.bean.ZhiHuItem;
import com.spring_ballet.looklook.util.OkHttpUtil;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
public class ZhihuNewsActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private SwipeRefreshLayout refreshLayout;
private List<Story> storyList;
private ZhiHuNewsAdapter adapter;
private DrawerLayout drawerLayout;
private SimpleDateFormat format;
/*使用安卓的SimpleDateFormat,对API有要求,所以这里导的包是java的SimpleDateFormat 类*/
private Date date;
private int datePage = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_zhihu_news);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolBar_zhihu);
toolbar.setTitle(R.string.zhihu_daily);
/*
要在setSupportActionBar之前设置标题才有用
如果想在后面改标题,当有CollapsingToolbarLayout时,需要获取collasping的实例并使用该实例的setTitle方法,即collapsingToolbarLayout.setTitle(newsContent.title);才行,如果没有这个控件,我现在也不清楚怎么设置,可以尝试一下
*/
setSupportActionBar(toolbar);
drawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
//这个格式是知乎日报api的要求格式
date = new Date();
NavigationView navigationView = (NavigationView) findViewById(R.id.navigationView);
navigationView.setItemIconTintList(null);
//设置为null可以使item的icon颜色显示出来
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.item_meizi:
SharedPreferences.Editor editor = getSharedPreferences(“ActivityRecord”, 0).edit();
editor.putInt(“activity”, 0);
editor.apply();
//这里实现了上文所说的保存最后的活动记录
Intent meiziIntent = new Intent(ZhihuNewsActivity.this, MeiziActivity.class);
startActivity(meiziIntent);
finish();
//结束这个活动并break,这里的break不能省略
break;
case R.id.item_zhihu:
Toast.makeText(ZhihuNewsActivity.this, “改变当前对应item颜色”, Toast.LENGTH_SHORT).show();
//这句话是我打算实现的目标
break;
default:
}
return true;
}
});
refreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout_zhihu);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView_zhihu);
refreshLayout.setColorSchemeResources(R.color.colorAccent, R.color.colorPrimary);
refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new GetZhiHuNews().execute(“https://news-at.zhihu.com/api/4/news/before/”
+ format.format(new Date(date.getYear(), date.getMonth(), date.getDay() - (datePage++))));
}
});
new GetZhiHuNews().execute(“https://news-at.zhihu.com/api/4/news/before/”
+ format.format(new Date(date.getYear(), date.getMonth(), date.getDay() - (datePage++))));
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE
&& !recyclerView.canScrollVertically(1)) {
/*canScrollVertically(1)代表是否可以垂直滑动,正上,负下,还有一个canScrollHorizontally,正右负左;
这里是判断是否到达底部,到达则刷新
new GetZhiHuNews().execute(“https://news-at.zhihu.com/api/4/news/before/”
+ format.format(new Date(date.getYear(), date.getMonth(), date.getDay() - (datePage++))));
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
});
}
private class GetZhiHuNews extends AsyncTask<String, Void, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
refreshLayout.setRefreshing(true);
}
@Override
protected String doInBackground(String... strings) {
return new OkHttpUtil().getData(strings[0]);
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
if (!TextUtils.isEmpty(s)) {
Gson gson = new Gson();
if (storyList == null || storyList.size() == 0) {
ZhiHuItem zhiHuItem = gson.fromJson(s, ZhiHuItem.class);
storyList = zhiHuItem.stories;
} else {
ZhiHuItem zhiHuItem = gson.fromJson(s, ZhiHuItem.class);
if (zhiHuItem != null) {
storyList.addAll(zhiHuItem.stories);
}
}
if (adapter == null) {
recyclerView.setAdapter(adapter = new ZhiHuNewsAdapter(ZhihuNewsActivity.this, storyList));
} else {
adapter.notifyDataSetChanged();
}
}
refreshLayout.setRefreshing(false);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
drawerLayout.openDrawer(GravityCompat.START);
break;
default:
}
return super.onOptionsItemSelected(item);
}
}
``
package com.spring_ballet.looklook.util;
3类似ZhiHuNewsContent这些类就不上传了,根据返回数据以及个人需求定制就可以了。
4.这个是工具类,使用okhttp获取数据,之所以没在这里开线程,是因为使用这个的时候都是在asynctask里。
import java.io.IOException;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class OkHttpUtil {
public String getData(String url){
try {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
return response.body().string();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
`
好累啊,一个小demo写着不简单,这样再写一篇博客就更累了,今天就先到这里吧,等我把demo传到github上去吧。