寒光博客

【Android】关于menu的综合练习作业
前言 本次练习基于一言的Api,对json数据进行简单分析和封装。 AKP:cn.dxoca.menu_exer...
扫描右侧二维码阅读全文
29
2020/04

【Android】关于menu的综合练习作业

前言

本次练习基于一言的Api,对json数据进行简单分析和封装。

此处内容需要评论回复后(审核通过)方可阅读。

AKP:cn.dxoca.menu_exercise.apk
测试apk安卓10安装不了
QQ截图20200430142328.png

详细演示(pc右击用新窗口打开 高清):
Menu.gif

  • 首页
    显示一言的句子和来源 点击文本标签可获取新的句子
    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标签的宽度是上一个句子的
QQ截图20200430142403.png

顶部状态栏透明

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();
                }
            }
        });
    }
}
本文作者:Author:     文章标题:【Android】关于menu的综合练习作业
本文地址:https://dxoca.cn/StudyNotes/343.html       百度已收录
版权说明:若无注明,本文皆为“Dxoca's blog (寒光博客)”原创,转载请保留文章出处。
Last modification:June 7th, 2020 at 01:42 am
如果觉得我的文章对你有用,请随意赞赏

Leave a Comment

One comment

  1. 乐心湖 Edge 83.0.478.37 Windows 10 中国 广东 汕头

    ୧(๑•̀⌄•́๑)૭ 同款IDEA,有机会我也学学安卓