从零开始用Andrid Studio开发一个简单的垃圾分类查询APP(4) —完结篇
作者:互联网
已经是写这个小APP的第四天了,今天我们继续看看能实现到什么程度。
(续)1.搜索结果页面布局
上个帖子中我们已经决定了就用ListView进行布局,接下来就是我们美化定制这个ListView了。
关于定制ListView,我们尝试跟着课本走一次:
新建一个garbages文件夹,用于放我们的“垃圾”,然后在其中新建一个Garbage_list类,用于作为ListView的适配器的适配类型。
我们在第二个帖子里已经决定了,在这个选项里面放的是“名字”和“分类”,代码如下:
public class Garbage_list {
private JSONObject search_result= MainActivity.Search_JSON;
private String name;
private int garbage_type; //0是可回收,1是有害垃圾,2是厨余垃圾,3是干垃圾(其它垃圾)
private String[] garbage_type_string={"可回收垃圾","有害垃圾","厨余垃圾","其它垃圾(干垃圾)"};
public Garbage_list(JSONObject the_garbage_JSON) throws JSONException {
name=the_garbage_JSON.getString("name");
garbage_type=Integer.parseInt(the_garbage_JSON.getString("type"));
}
public String getName(){
return name;
}
public String getType(){
return garbage_type_string[garbage_type];
}
}
这里的代码随便写写,很简单的,大家应该都看得懂,其中只涉及到一个字符串转数字。
接下来我们为选项指定一个自定义布局,同样,在layout目录下新建一个garbage_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/garbage_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"/>
<TextView
android:id="@+id/garbage_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"/>
</LinearLayout>
我们写了两个TextView,且都设置为竖直居中。
然后我们创建一个自定义适配器,将泛型指定为Garbage_list类,(泛型是甚么东西?不知道,推荐不知道的朋友们百度一下,我也不细说了。)
我们在垃圾文件夹中新建一个类Garbage_adapter,代码如下:
public class Garbage_adapter extends ArrayAdapter {
private int resourceId;
public Garbage_adapter(Context context, int textViewResourceId, List<Garbage_list> objects){
super(context,textViewResourceId,objects);
resourceId=textViewResourceId;
}
@Override
public View getView(int position, View convertView, ViewGroup parent){
Garbage_list garbage_list= (Garbage_list) getItem(position);
View view= LayoutInflater.from(getContext()).inflate(resourceId, parent,false);
TextView garbageName=(TextView)view.findViewById(R.id.garbage_name);
TextView garbageType=(TextView)view.findViewById(R.id.garbage_type);
garbageName.setText(garbage_list.getName());
garbageType.setText(garbage_list.getType());
return view;
}
}
这里我也不太懂,大概就是把之前的类实时传给布局文件的意思吧。
接下来我们为SearchActivity中修改代码:
public class SearchActivity extends AppCompatActivity {
private JSONObject search_result=MainActivity.Search_JSON; //用于接收MainActivity中的搜索结果
private List<Garbage_list> garbageList=new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
ActionBar actionbar=getSupportActionBar();
if(actionbar!=null){
actionbar.hide();
}
try {
init_garbage_list();
} catch (JSONException e) {
e.printStackTrace();
}
Garbage_adapter adapter=new Garbage_adapter(SearchActivity.this, R.layout.garbage_list, garbageList);
ListView listView=(ListView)findViewById(R.id.search_listview);
listView.setAdapter(adapter);
}
private JSONObject make_the_JSON(int i) throws JSONException { //用于将JSON转换为字符串数组
JSONArray newslist=search_result.getJSONArray("newslist");
String[] name=new String[newslist.length()];
String newslistString=new String();
JSONObject the_garbage_JSON=new JSONObject(); //具体某一项的json ,可以通过getstring获得其中具体的项
newslistString=newslist.getString(i);
the_garbage_JSON=new JSONObject(newslistString);
// name[i]=the_garbage_JSON.getString("name");
return the_garbage_JSON;
}
private void init_garbage_list() throws JSONException {
JSONArray newslist=search_result.getJSONArray("newslist");
for(int i=0;i<newslist.length();i++){
Garbage_list the_garbage=new Garbage_list(make_the_JSON(i));
garbageList.add(the_garbage);
}
}
}
运行一下:
好家伙,够接地气,书上的部分就结束了,因为书上是图片加文字,所以什么都不设置都能看,我们这个就不行了。
这里楼主首先试了试把garbage_list.xml改成RelativeLayout,结果发现页面切换不过去了,可能是因为我们现在的适配器没法适配这个的原因吧,所以我们只能回来继续用LinearLayout继续调试了,经过楼主的不断改动,终于是可以看了:如图:
代码如下:
<?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/garbage_name"
android:layout_width="245dp"
android:layout_height="60dp"
android:layout_alignParentTop="true"
android:layout_gravity="center_vertical"
android:layout_marginTop="0dp"
android:gravity="center_vertical"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:textSize="20dp" />
<TextView
android:id="@+id/garbage_type"
android:layout_width="165dp"
android:layout_height="60dp"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_gravity="center_vertical"
android:layout_marginTop="0dp"
android:layout_marginEnd="-6dp"
android:layout_marginRight="-6dp"
android:gravity="center"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
</LinearLayout
接下来我们依次为搜索页面的控件添加事件,首先是上面的搜索组合:
先声明一下控件和url:
private EditText text_search_garbage;
private Button btn_search_garbage;
String url_garbage="https://api.tianapi.com/txapi/lajifenlei/index?key=xxxxxxxxxxxxxxxxxxxxxxxxxx&word=";
然后复制MainActivity中的相应部分过来改一下,基本上把MainActivity改成SearchActivity就可以了,然后加个结束页面,代码如下:
private void init_search(){
View view = getWindow().peekDecorView();
if (view != null) {//这里是网络访问的代码,获取服务
InputMethodManager inputmanger = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
inputmanger.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
initData_search();
}
Handler handler_search=new Handler(new Handler.Callback() {//首先通过handler发送信息
@Override
public boolean handleMessage(@NonNull Message msg) {
switch (msg.what){
case 0:
Toast.makeText(SearchActivity.this,"网络错误",Toast.LENGTH_LONG).show();
break;
case 1:
String json=(String)msg.obj;
try{
MainActivity.Search_JSON=new JSONObject(json);
Intent intent=new Intent();
intent.setClass(SearchActivity.this, SearchActivity.class);
startActivity(intent);
finish(); //结束掉现在的页面,直接返回主页。(假装可以刷新)
break;
}catch (JSONException e){
e.printStackTrace();
}
default:
throw new IllegalStateException("Unexpected value: " + msg.what);
}
return false;
}
});
private void initData_search(){ //接着用这个方法调用handler,并把返回的信息放入TextView
// handler_beauty.sendEmptyMessage(1);
String data=text_search_garbage.getText().toString();
if(TextUtils.isEmpty(data)){//如果内容为空,弹出toast消息,不为空则执行164行以后的代码
Toast.makeText(SearchActivity.this,"垃圾名称不能为空!",Toast.LENGTH_SHORT).show();
}
else{
Okhttp_work.OkHttpGet(url_garbage+data, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String content=response.body().string();
Message message=new Message();
message.what=1;
message.obj=content;
handler_search.sendMessageDelayed(message,10);
}
});
}
}
最后在onCreate中加入定义和监听器就完成了:
text_search_garbage=findViewById(R.id.search_edit_text);
btn_search_garbage=findViewById(R.id.button_search);
try {
init_garbage_list();
} catch (JSONException e) {
e.printStackTrace();
}
Garbage_adapter adapter=new Garbage_adapter(SearchActivity.this, R.layout.garbage_list, garbageList);
ListView listView=(ListView)findViewById(R.id.search_listview);
listView.setAdapter(adapter);
btn_search_garbage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
init_search();
}
});
测试一下是成功的,这里我就不截图了。
接下来是为ListView添加点击事件,让我们能够进入详情页面:
这一段书上又没有介绍了,所以又需要我们操起老本行了,
这里楼主要感谢百度知道 Android开发 关于ListView的点击事件 中的第一个答案,让楼主成功达成了点击事件。
我们依旧是先在SearchActivity中声明两个变量:
private ListView garbageList_View;
public int garbage_id;
然后写ListView的点击事件:
garbageList_View=findViewById(R.id.search_listview);
garbageList_View.setOnItemClickListener(new AdapterView.OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
garbage_id=i;
Intent intent=new Intent();
intent.setClass(SearchActivity.this, DetailActivity.class);
startActivity(intent);
}
});
这样我们在打开新页面的同时,也把点击的选项id放入了全局变量garbage_id中,这样下个页面就可以直接调用这个参数了。
OK!搜索结果页面完成!(有木有想大吼一声啊~)
2.进入详情页面
做到这里,楼主发现一个大问题,我们没有图片,所以这波进入详情之后会是很生硬的文字堆叠,很丑,如果这波有图片,那我们这将会是绝杀,可惜有不得。
有不得的话,那自然是上来一堆TextView,一堆setText,就完事了,虽说这样有点太简单了,不过没关系,我们后面再画个一两个小时专门美化一下就好了。
现在先来实现吧:
先新建一个normal_detail.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="60dp"
android:background="@drawable/title_bg">
</RelativeLayout>
作为空白的导航栏,然后修改activity_detail.xml代码如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".DetailActivity">
<include
android:id="@+id/include_detail_title"
layout="@layout/normal_title"
app:layout_constraintBottom_toTopOf="@+id/main_image" />
<TextView
android:id="@+id/detail_garbage_name"
android:layout_width="266dp"
android:layout_height="69dp"
android:layout_below="@+id/include_detail_title"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_marginStart="0dp"
android:layout_marginLeft="0dp"
android:layout_marginTop="3dp"
android:text="暂时没有网络连接~" />
<TextView
android:id="@+id/detail_garbage_type"
android:layout_width="146dp"
android:layout_height="69dp"
android:layout_below="@+id/include_detail_title"
android:layout_marginStart="0dp"
android:layout_marginLeft="0dp"
android:layout_marginTop="3dp"
android:layout_toEndOf="@+id/detail_garbage_name"
android:layout_toRightOf="@+id/detail_garbage_name"
android:text="暂时没有网络连接~" />
<TextView
android:id="@+id/detail_garbage_explain"
android:layout_width="match_parent"
android:layout_height="135dp"
android:layout_below="@+id/include_detail_title"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_marginStart="0dp"
android:layout_marginLeft="0dp"
android:layout_marginTop="74dp"
android:text="暂时没有网络连接~" />
<TextView
android:id="@+id/detail_garbage_contain"
android:layout_width="match_parent"
android:layout_height="122dp"
android:layout_below="@+id/include_detail_title"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_marginStart="0dp"
android:layout_marginLeft="0dp"
android:layout_marginTop="210dp"
android:text="暂时没有网络连接~" />
<TextView
android:id="@+id/detail_garbage_tips"
android:layout_width="match_parent"
android:layout_height="78dp"
android:layout_below="@+id/include_detail_title"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginTop="332dp"
android:layout_marginEnd="0dp"
android:layout_marginRight="0dp"
android:text="暂时没有网络连接~" />
</RelativeLayout>
看着多,其实就是随便拖了五个TextView,字体什么的我们先不管,随便放一下,后面再改。最后修改DetailActivity代码如下:
public class DetailActivity extends AppCompatActivity {
private TextView garbage_name;
private TextView garbage_type;
private TextView garbage_explain;
private TextView garbage_contain;
private TextView garbage_tips;
private JSONObject search_result=MainActivity.Search_JSON;
private int detail_garbage_id=SearchActivity.garbage_id;
private String[] garbage_type_string={"可回收垃圾","有害垃圾","厨余垃圾","其它垃圾(干垃圾)"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
ActionBar actionbar=getSupportActionBar();
if(actionbar!=null){
actionbar.hide();
}
garbage_name=findViewById(R.id.detail_garbage_name);
garbage_type=findViewById(R.id.detail_garbage_type);
garbage_explain=findViewById(R.id.detail_garbage_explain);
garbage_contain=findViewById(R.id.detail_garbage_contain);
garbage_tips=findViewById(R.id.detail_garbage_tips);
try {
garbage_name.setText(make_the_String("name"));
} catch (JSONException e) {
e.printStackTrace();
}
try {
garbage_type.setText(garbage_type_string[Integer.parseInt(make_the_String("type"))]);
} catch (JSONException e) {
e.printStackTrace();
}
try {
garbage_explain.setText(make_the_String("explain"));
} catch (JSONException e) {
e.printStackTrace();
}
try {
garbage_contain.setText(make_the_String("contain"));
} catch (JSONException e) {
e.printStackTrace();
}
try {
garbage_tips.setText(make_the_String("tip"));
} catch (JSONException e) {
e.printStackTrace();
}
}
private String make_the_String(String need) throws JSONException { //用于将JSON转换为字符串数组
JSONArray newslist=search_result.getJSONArray("newslist");
// String[] name=new String[newslist.length()];
String newslistString=new String();
JSONObject the_garbage_JSON=new JSONObject(); //具体某一项的json ,可以通过getstring获得其中具体的项
newslistString=newslist.getString(detail_garbage_id);
the_garbage_JSON=new JSONObject(newslistString);
// name[i]=the_garbage_JSON.getString("name");
return the_garbage_JSON.getString(need);
}
}
相信对于一直看到这里的朋友们这个已经很简单了,我也就不细说了,其实就是用之前编写的方法工具复制过来用罢了。测试一下:
成功显示,没有bug。
接下来就到我们的三岔路口了,我们是该开始着手美化APP呢,还是继续研究添加数据库的功能呢?
楼主想了想,还是算了吧,头已经在发热了,急需一个水冷来降温了,就不做什么数据库了,从刚开始接触数据库一直到现在,楼主真的一听到数据库就头大,什么连接什么的,当时用python连接数据库差点没把我送走。
所以我的下一步就是轻松愉快的美化APP啦!(“我要补充”,删~;“EditActivity”,删。)
美化的步骤我就不放在这里啦,毕竟也没剩多少技术含量了。
大家如果有兴趣可以用我博客里的代码自己操作一番,源码都在博客里面附着,所以楼主就不单独给大家打包源码了,毕竟楼主也是为了自己完成作业嘛,哈哈^ _ ^。
完结
(ps:楼主以后也会不断更新更多有意思的小知识的,所以就点一下辣个大拇指和关注吧,它们会亮的哇!QωQ)
最后附上楼主美化完的截图(加了几个无伤大雅的简单页面):
另外主页的按钮点进去是相应的介绍,“了解更多”按钮是打开百度网页(/捂脸)。是不是感觉好多了QwQ
标签:完结篇,search,String,garbage,Andrid,private,Studio,new,id 来源: https://blog.csdn.net/qq_44178379/article/details/110589712