太久没写Android了,今天有同学布置了这个题目,花了一上午的时间做了做:
要求:
1)围绕疫情背景下某一主题,要体现正能量
2)实现首页(app着陆页),可包含app标题、背景图等;需支持横屏显示不同布局
3)实现列表Activity,其包含10项以上内容,每项显示缩略图与标题文字;需支持屏幕上下滚动
4)实现详情Activity,其包含每条内容的介绍详情,包括图片与文字
5)点击首页进入列表Activity;点击列表Activity中的某条内容,跳转到其相应的详情Activity;详情Activity提供返回按钮,返回列表Activity
6)app支持中、英文两个版本(英文内容不要求精准翻译,可使用翻译引擎)
提交文件:
1)报告:选题背景、实现技术、关键核心代码及解析(切忌粘贴大段代码)、截图演示、心得体会(对于主题内容的心得+app开发的心得)
2)源码:仅提交与你所写的代码文件,如:MainActivity.java、res/layout/*、res/drawable/*、res/values/*、AndroidManifest.xml等(切忌提交整个工程,如gradle等)
3)报告文件名:学号+姓名.docx
4)源码请压缩为一个文件,文件名:学号+姓名.zip
评分标准:
1)切合题意:是否围绕疫情,体现正能量
2)实现技术:是否以优雅的形式实现功能,如:使用adapter、数组、数据传递,避免使用硬编码
3)设计美感:界面设计的美感是否符合主流审美
4)报告质量:描述是否清晰、重点是否突出、排版是否科学
直接拿之前卡片布局的那篇文章改了改,效果展示:
首页展示:
支持横竖屏不同布局:
进入详情,支持返回,不过借助网易新闻的web页面,没有再往里面做了:
用的免费的百度翻译api做的内容翻译,所以很慢,而且经常会出现错误反馈的bug:
下面是源码:
主活动:
public class MainActivity extends AppCompatActivity {
private List<Fruit> fruitList = new ArrayList<>();
private FruitAdapter adapter;
private SwipeRefreshLayout swipeRefreshLayout;
private Boolean focusOn = true; // 中英文切换
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
GridLayoutManager layoutManager;
initFruits();
if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
layoutManager = new GridLayoutManager(this, 1);
} else {
layoutManager = new GridLayoutManager(this, 2);
}
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(layoutManager);
adapter = new FruitAdapter(fruitList);
recyclerView.setAdapter(adapter);
swipeRefreshLayout = findViewById(R.id.swipe_refresh);
swipeRefreshLayout.setColorSchemeResources(R.color.colorPrimary);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
refreshFruits();
}
});
refreshFruits();
}
private void refreshFruits() {
new Thread(new Runnable() {
@Override
public void run() {
try {
if(focusOn){Thread.sleep(2000);}
else {Thread.sleep(15000);}
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
@Override
public void run() {
initFruits();
adapter.notifyDataSetChanged();
swipeRefreshLayout.setRefreshing(false);
if (fruitList.isEmpty()){
if(focusOn){Toast.makeText(MainActivity.this, "请连接网络后重试", Toast.LENGTH_SHORT).show();}
else {Toast.makeText(MainActivity.this, "Please connect to the network and try again", Toast.LENGTH_SHORT).show();}
}
}
});
}
}).start();
}
private void initFruits() {
String url = "https://c.m.163.com/news/s/S1580274169223.html?plateform=wap";
HttpUtil.sendOkHttpRequest(url, new Callback(){
@Override
public void onResponse(@NotNull Call call, @NotNull Response response)throws IOException {
// 得到服务器返回的具体内容
String responseData = response.body().string();
String pattern = "\\[\\{\"docs\":(.*),\"banner\":\"http";
Matcher m = Pattern.compile(pattern).matcher(responseData);
if (m.find()) {
responseData = m.group(1);
}
JSONArray jsonArray = null;
try {
jsonArray = new JSONArray(responseData);
fruitList.clear();
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
String title = jsonObject.getString("title");
String url = jsonObject.getString("url");
String imgsrc = jsonObject.getString("imgsrc");
if(focusOn){fruitList.add(new Fruit(title, url, imgsrc));}
else {HttpUtil.sendTranslateRequest(title, url, imgsrc, fruitList);}
}
} catch (JSONException | NoSuchAlgorithmException | InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e){
// 对异常情况处理
fruitList.add(new Fruit("错误", "https://blog.csdn.net/qq_41205771/category_9647051.html", "https://dss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=4249322567,890225457&fm=26&gp=0.jpg"));
}
});
}
// 加载toolbar.xml菜单
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar, menu);
return true;
}
// 处理按钮点击事件
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.mongo:
if(focusOn){
Toast.makeText(this, "系统语言切换为英文", Toast.LENGTH_SHORT).show();
focusOn = false;
}else {
refreshFruits();
Toast.makeText(this, "Switch system language to Chinese", Toast.LENGTH_SHORT).show();
focusOn = true;
}
break;
default:
break;
}
return true;
}
}
// 工具
class HttpUtil {
// 网络工具
public static void sendOkHttpRequest(String address, okhttp3.Callback callback){
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.addHeader("user-agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36")
.url(address)
.build();
client.newCall(request).enqueue(callback);
}
// 翻译工具
public static void sendTranslateRequest(String sentence, final String url, final String imgSrc, final List<Fruit> fruitList) throws NoSuchAlgorithmException, UnsupportedEncodingException, InterruptedException {
Thread.sleep(500);
String appid = "????????";
String key = "???????";
long l = System.currentTimeMillis();
String salt = Integer.toString((int)( l % 999999));
String md5 = appid + sentence + salt + key;
MessageDigest m = MessageDigest.getInstance("MD5");
m.update(md5.getBytes("UTF8"));
byte s[] = m.digest();
StringBuilder result = new StringBuilder();
for (byte b : s) {
result.append(Integer.toHexString((0x000000FF & b) | 0xFFFFFF00).substring(6));
}
String theUrl = "http://api.fanyi.baidu.com/api/trans/vip/translate?from=zh&to=en&appid="+appid+"&q="+sentence+"&salt=" + salt + "&sign="+result;
HttpUtil.sendOkHttpRequest(theUrl, new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
fruitList.add(new Fruit("错误", "https://blog.csdn.net/qq_41205771/category_9647051.html", "https://dss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=4249322567,890225457&fm=26&gp=0.jpg"));
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
String responseData = response.body().string();
String theTitle = "错误";
try {
JSONObject jsonObj = new JSONObject(responseData);
theTitle = ((JSONObject) ((JSONArray) jsonObj.get("trans_result")).get(0)).get("dst").toString();
} catch (JSONException e) {
e.printStackTrace();
}
fruitList.add(new Fruit(theTitle, url, imgSrc));
}
});
}
布局和之前的卡片布局一模一样,就不贴了。