前言
本次练习基于一言的Api,对json数据进行简单分析和封装。
AKP:cn.dxoca.menu_exercise.apk
测试apk安卓10安装不了
详细演示(pc右击用新窗口打开 高清):
-
首页
显示一言的句子和来源点击文本标签可获取新的句子
Json解析 :Hitokoto.class
对一言API进行解析封装 用到Thread HtmlService JSONObject- 菜单
基于PopupMenu的ViewButton菜单- 设置
Setting.class
达到通过Setting改变首页请求返回句子类型(json)
数据传回
更改参数X:https://v1.hitokoto.cn/?encode=json&c=X
- 历史
History.class
记录每一条String数据
数据传入,暂时没有写回传 导致重新返回首页数据丢失
记录首页获取的每一条json对象 通过Queue队列存储对象
但是由于不同页面见对象数据传送和回传及不明BUG (暂时还未找到 似乎是线程问题)
长按项目可复制到剪切板
所以改为有限空间Sting数组来暂存intent.putExtra("hitokoto", str);
- 更新
Update.class
暂时本地
ProgressBar 进度条自增长 用到Thread(线程)和Handler
可间隔时间执行任务
- 设置
- 菜单
-
BUG更新:
Setting设置后首页再次发生跳转 设置数据丢失
美化与布局
顶部:隐藏标题栏 顶部状态栏透明 添加按钮菜单
句子:这里的句子是解析json返回的,长度不定,初始化设定的是内容多宽就多宽,宽到屏宽就换行
但是这不是我想要的效果,并且在句子的两边有一个引号给括起来 所以布局有点点麻烦
用了temp标签来转存 句子内容和 句子的宽度
通过计算屏宽的80%来限制。
//取屏幕宽度
final WindowManager wm = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
final int width = wm.getDefaultDisplay().getWidth();
text_hitokoto.setWidth((int) (width * 0.8));//固定 边框! 动态边框bug暂未修复
其中还有一个bug大概也是线程导致的 需要话时间慢慢调 就是引号标签的位置所获得的temp标签的宽度是上一个句子的
顶部状态栏透明
https://www.jianshu.com/p/d32c6a0a4310
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return;
}
Window window = this.getWindow();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
int option = window.getDecorView().getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
window.getDecorView().setSystemUiVisibility(option);
window.setStatusBarColor(Color.TRANSPARENT);
} else {
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
隐藏标题栏
去除标题栏
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
一定写在: setContentView()
之前
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
}
PopupMenu
PopupMenu想放哪就可以放哪PopupMenu官方参考
绑定按钮
final ImageView imageVie = findViewById(R.id.main_img);
imageVie.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
showPopupMenu(imageVie);
}
});
PopupMenu方法
private void showPopupMenu(View view) {
// View当前PopupMenu显示的相对View的位置
PopupMenu popupMenu = new PopupMenu(this, view);
// menu布局
popupMenu.getMenuInflater().inflate(R.menu.main, popupMenu.getMenu());
// menu的item点击事件
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
Toast.makeText(getApplicationContext(), item.getTitle(), Toast.LENGTH_SHORT).show();
return false;
}
});
// PopupMenu关闭事件
popupMenu.setOnDismissListener(new PopupMenu.OnDismissListener() {
@Override
public void onDismiss(PopupMenu menu) {
Toast.makeText(getApplicationContext(), "关闭PopupMenu", Toast.LENGTH_SHORT).show();
}
});
popupMenu.show();
}
核心代码
MainActivity.calss
package cn.dxoca.menu_exercise;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.PopupMenu;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import java.util.LinkedList;
import java.util.Queue;
public class MainActivity extends AppCompatActivity {
final Queue<Hitokoto> queueHit = new LinkedList<>();
String[] str = new String[100];
int i = 0;
final char[] x = new char[1];//初始化a setting设置
TextView text_sentence;//句子类型
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);//去除标题栏 一定在 下面这句之前
setContentView(R.layout.activity_main);
//取屏幕宽度
final WindowManager wm = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
final int width = wm.getDefaultDisplay().getWidth();
final TextView text_hitokoto, text_from, text_temp;
setTitle("Hitokoto");
text_hitokoto = findViewById(R.id.text_hitokoto);
text_from = findViewById(R.id.text_from);
text_temp = findViewById(R.id.text_temp);
text_sentence = findViewById(R.id.text_sentence);
text_temp.setVisibility(View.INVISIBLE);//隐藏
//状态栏透明 https://www.jianshu.com/p/d32c6a0a4310
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return;
}
Window window = this.getWindow();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
int option = window.getDecorView().getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
window.getDecorView().setSystemUiVisibility(option);
window.setStatusBarColor(Color.TRANSPARENT);
} else {
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
//菜单按钮绑定
final Button menu ;
menu=findViewById(R.id.button3);
menu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showPopupMenu(menu);
}
});
//为history 准备 队列bug暂未解决
queueHit.add(new Hitokoto(text_hitokoto, text_from, text_temp, x[0]));//有问题 并没有产生add 改用直接拿标签
// str[i++]= text_hitokoto.getText().toString()+" ["+text_from.getText()+"]"; 这次是取最开始的 所以 不拿
// System.out.println(str[i-1]);
text_hitokoto.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//显示一言 句子 来源 临时 把握宽度
queueHit.add(new Hitokoto(text_hitokoto, text_from, text_temp, x[0]));
System.out.println(queueHit.peek().getId());
str[i++] = text_hitokoto.getText().toString() + "" + text_from.getText() + "";
System.out.println(str[i - 1]);
}
});
//线程BUG 还未解决!!!
text_temp.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
// //调整宽度
// int temp = text_temp.getWidth();
// if (temp > width * 0.8) {
// text_hitokoto.setWidth((int) (width * 0.8));
// } else {
// text_hitokoto.setWidth(temp);
// }
text_hitokoto.setWidth((int) (width * 0.8));//固定 边框! 动态边框bug暂未修复 如上代码
}
});
}
/**
* 数据回传
* @param requestCode
* @param resultCode
* @param data
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == 101) {//setting
x[0] = data.getCharExtra("x", 'a');
text_sentence.setText("句子类型:"+x[0]);
}
}
/**
* View 当前PopupMenu显示的相对View的位置
* @param view 菜单按钮
*/
private void showPopupMenu(View view) {
PopupMenu popupMenu = new PopupMenu(this, view);
// menu布局绑定
popupMenu.getMenuInflater().inflate(R.menu.bar_menu, popupMenu.getMenu());
// menu的item点击事件
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
Intent intent = new Intent();
switch (item.getItemId()) {
case R.id.setting:
intent.setClass(MainActivity.this, Setting.class);
startActivityForResult(intent, 101);
break;
case R.id.history:
// int i = 0;
// String[] res = new String[queueHit.size()];
// Hitokoto temp;
//队列中的数据 去出到String 直接传对象遇到问题
// while (!queueHit.isEmpty()) {
// temp = queueHit.poll();
// res[i++] = temp.getHitokoto() + " [" + temp.getFrom() + "]";
// System.out.println("+++++" + res[i - 1]);
// }
intent.setClass(MainActivity.this, History.class);
intent.putExtra("hitokoto", str);
startActivity(intent);
break;
case R.id.update:
intent.setClass(MainActivity.this, Update.class);
startActivity(intent);
break;
}
return false;
}
});
// PopupMenu关闭事件
popupMenu.setOnDismissListener(new PopupMenu.OnDismissListener() {
@Override
public void onDismiss(PopupMenu menu) {
Toast.makeText(getApplicationContext(), "关闭PopupMenu", Toast.LENGTH_SHORT).show();
}
});
popupMenu.show();
}
}
Hitokoto.class
package cn.dxoca.menu_exercise;
import android.util.Log;
import android.widget.TextView;
import org.json.JSONObject;
// android获取网页接口JSON数据 https://blog.csdn.net/lpcrazyboy/article/details/80296627
public class Hitokoto {
private int id;
private String hitokoto, from, creator;
final String[] html = new String[1];
Hitokoto() { }
/**
* @param text_hitokoto
* @param text_from
* @param text_temp
* @param x 句子类型
*/
Hitokoto(final TextView text_hitokoto, final TextView text_from, final TextView text_temp, final char x) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
html[0] = HtmlService.getHtml("https://v1.hitokoto.cn/?encode=json&c=" + x);
JSONObject obj = new JSONObject(html[0]);
Log.i("jsonData", html[0]);
final Hitokoto hitokoto = new Hitokoto(obj.getInt("id"), obj.getString("hitokoto"), obj.getString("from"), obj.getString("creator"));
// Hitokoto hitokoto = new Hitokoto();
// hitokoto.setHitokoto(obj.getString("hitokoto"));
// hitokoto.setFrom(obj.getString("from"));
// hitokoto.setCreator(obj.getString("creator"));
// hitokoto.setId(obj.getInt("id"));
System.out.println(x + ":" + hitokoto.getHitokoto() + " ————" + hitokoto.getFrom());
text_hitokoto.post(new Runnable() {//拉出线程队列
@Override
public void run() {
// text_hitokoto.setText("『 " + hitokoto.getHitokoto() + " 』");
text_temp.setText(hitokoto.getHitokoto());
text_hitokoto.setText(text_temp.getText());
text_from.setText(" —— 「" + hitokoto.getFrom() + "」");
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
}
Hitokoto(int id, String hitokoto, String from, String creator) {
setId(id);
setCreator(creator);
setFrom(from);
setHitokoto(hitokoto);
}
public void setId(int id) {
this.id = id;
}
public void setHitokoto(String hitokoto) {
this.hitokoto = hitokoto;
}
public void setFrom(String from) {
this.from = from;
}
public void setCreator(String creator) {
this.creator = creator;
}
public int getId() {
return id;
}
public String getHitokoto() {
return hitokoto;
}
public String getFrom() {
return from;
}
public String getCreator() {
return creator;
}
}
HtmlService.class
package cn.dxoca.menu_exercise;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class HtmlService {
public static String getHtml(String path) throws Exception {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5 * 1000);
InputStream inStream = conn.getInputStream();//通过输入流获取html数据
byte[] data = readInputStream(inStream);//得到html的二进制数据
String html = new String(data, "UTF-8");
return html;
}
public static byte[] readInputStream(InputStream inStream) throws Exception{
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while( (len=inStream.read(buffer)) != -1 ){
outStream.write(buffer, 0, len);
}
inStream.close();
return outStream.toByteArray();
}
}
Setting.class
package cn.dxoca.menu_exercise;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.RadioGroup;
import androidx.appcompat.app.AppCompatActivity;
public class Setting extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_setting);
setTitle("Setting");
// RadioButton a, b, c, d, e, f, g, h, i, j, k, l, m; 不需要定义RB
RadioGroup item;
Button bt;
bt = findViewById(R.id.button);
item = findViewById(R.id.item);
final Intent intent = new Intent();
final char[] x = new char[1];
item.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId) {
case R.id.radioButton:
x[0] = 'a';
break;
case R.id.radioButton2:
x[0] = 'b';
break;
case R.id.radioButton3:
x[0] = 'c';
break;
case R.id.radioButton4:
x[0] = 'd';
break;
case R.id.radioButton5:
x[0] = 'e';
break;
case R.id.radioButton6:
x[0] = 'f';
break;
case R.id.radioButton7:
x[0] = 'g';
break;
case R.id.radioButton8:
x[0] = 'h';
break;
case R.id.radioButton9:
x[0] = 'i';
break;
case R.id.radioButton10:
x[0] = 'j';
break;
case R.id.radioButton11:
x[0] = 'k';
break;
case R.id.radioButton12:
x[0] = 'l';
break;
case R.id.radioButton13:
x[0] = 'a';//默认a
break;
}
System.out.println("句子:" + x[0]);
}
});
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
intent.setClass(Setting.this, MainActivity.class);
intent.putExtra("x", x[0]);
final int REQUEST_CODE = 101;
// startActivityForResult(intent, REQUEST_CODE);//回传activity
setResult(101,intent);
finish();
}
});
}
}
History.class
package cn.dxoca.menu_exercise;
import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class History extends AppCompatActivity {
ListView list;
Toast myToast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_history);
Intent intent = getIntent();
// Queue<Hitokoto> hitokoto = (Queue<Hitokoto>) getIntent().getSerializableExtra("hitokoto");
setTitle("History");
String[] str = intent.getStringArrayExtra("hitokoto");
int count = 0;//计数
for (int i = 0; i < str.length; i++) {
if (str[i] == null) break;
count++;
System.out.println(str[i]);
System.out.println("+++");
}
String[] res=new String[count];
for (int i = 0; i < res.length; i++) {
res[i]=str[i];
}
list = findViewById(R.id.list);
//定义数组适配器
ArrayAdapter<String> myAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, res);
list.setAdapter(myAdapter);
//列表项目 单机 监听器
list.setOnItemClickListener((new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String str = parent.getItemAtPosition(position).toString();
if (myToast != null) {
myToast.cancel();
}
myToast = Toast.makeText(History.this, id + ":" + str, Toast.LENGTH_LONG);
myToast.show();
}
}));
//列表项目 长按 监听器【对话框】
list.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
final AlertDialog.Builder dialog=new AlertDialog.Builder(History.this);
dialog.setTitle("复制提醒");
dialog.setMessage("是否复制到剪切板") ;
dialog.setPositiveButton("确定",null);
dialog.setNegativeButton("取消",null);
dialog.create();
dialog.show();
return false;
}
});
}
}
Update.class
package cn.dxoca.menu_exercise;
import android.annotation.SuppressLint;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
public class Update extends AppCompatActivity {
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_update);
setTitle("Update");
final TextView t2, t3;
t2 = findViewById(R.id.textView2);
t3 = findViewById(R.id.textView3);
Button bt;
bt = findViewById(R.id.button2);
final ProgressBar pb;
pb = findViewById(R.id.progressBar);
final int[] status = {0};//记录PB进度
t2.setText("By:寒光 dxoca.cn");
pb.setVisibility(View.INVISIBLE);//隐藏
//创建一个更新进度的Handler
@SuppressLint("HandlerLeak") final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//表面该消息是有该程序发送的
if (msg.what == 0x111) {
pb.setProgress(status[0]);
if (status[0] == 100) {
t2.setText("已经是最新版本 By:寒光 dxoca.cn");
t3.setText("DO 1.0.0 Beta");
pb.setVisibility(View.INVISIBLE);//隐藏
}
}
}
};
bt.setOnScrollChangeListener(new View.OnScrollChangeListener() {
@Override
public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
}
});
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
t2.setText("正在检查更新...");
pb.setVisibility(View.VISIBLE);//显示
status[0]=0;
pb.setProgress(status[0]);
//启动线程执行任务
new Thread() {
@Override
public void run() {
super.run();
while (status[0] < 0x64) {
status[0]++;
doWork();//事件
//发送消息
handler.sendEmptyMessage(0X111);
}
}
}.start();
}
//线程任务
private void doWork() {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
本文地址:https://dxoca.cn/StudyNotes/343.html 百度已收录
版权说明:若无注明,本文皆为“Dxoca's blog (寒光博客)”原创,转载请保留文章出处。
୧(๑•̀⌄•́๑)૭ 同款IDEA,有机会我也学学安卓