首页 > 其他分享 >软件工程小米便签新增功能之--插入图片

软件工程小米便签新增功能之--插入图片

时间:2024-05-30 17:33:12浏览次数:25  
标签:便签 String img -- uri 软件工程 null local final

 【软件应用开发】小米便签APP维护开发_小米便签二次开发-CSDN博客

本文章旨在对上述文章一对一详细介绍,以方便入门的萌新使用:

        我们规划一下,

一。我们介绍一点小技巧:

        1.搜索:双击shift可以搜索,在末尾最后一步的时候有示例。

        2.自动改错:停在报错的位置,然后按Alt+Enter,会显示解决方案,然后按一下Enter即可自动修改文章,然后解决报错

        3.分屏展示

        4.导入图片,可以参考一下链接:Android studio导入资源,包括导入图片-CSDN博客

        4.我们大概只涉及到描述部分NoteEditActivity和框架部分note_edit(MiNotes\app\src\main\java\net\micode\notes\ui\NoteEditActivity.java+++++++++MiNotes\app\src\main\res\layout\note_edit.xml)

二。我们需要准备小米便签的开源代码

三。然后开始具体操作(我截图时尽量保留下上下文,方便读者定位)

,1.首先添加按钮(路径:MiNotes\app\src\main\res\layout\note_edit.xml)

<ImageButton
        android:id="@+id/add_img_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="7dp"
        android:layout_marginTop="600dp"
        android:layout_marginBottom="7dp"
        android:src="@android:drawable/ic_menu_gallery" />


 

2.然后替代原来的onCreate()方法(路径:MiNotes\app\src\main\java\net\micode\notes\ui\NoteEditActivity.java)

private final int PHOTO_REQUEST=1;

@Override

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.setContentView(R.layout.note_edit);

    if (savedInstanceState == null && !initActivityState(getIntent())) {
        finish();
        return;
    }
    initResources();

    //根据id获取添加图片按钮
    final ImageButton add_img_btn = (ImageButton) findViewById(R.id.add_img_btn);
    //为点击图片按钮设置监听器
    add_img_btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Log.d(TAG, "onClick: click add image button");
            //ACTION_GET_CONTENT: 允许用户选择特殊种类的数据,并返回(特殊种类的数据:照一张相片或录一段音)
            Intent loadImage = new Intent(Intent.ACTION_GET_CONTENT);
            //Category属性用于指定当前动作(Action)被执行的环境.
            //CATEGORY_OPENABLE; 用来指示一个ACTION_GET_CONTENT的intent
            loadImage.addCategory(Intent.CATEGORY_OPENABLE);
            loadImage.setType("image/*");
            startActivityForResult(loadImage, PHOTO_REQUEST);
        }
    });
}

3.同时添加一块代码(路径:MiNotes\app\src\main\java\net\micode\notes\ui\NoteEditActivity.java)

//获取文件的real path
public String getPath(final Context context, final Uri uri) {

    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

    // DocumentProvider
    if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
        // ExternalStorageProvider
//            if (isExternalStorageDocument(uri)) {
//                final String docId = DocumentsContract.getDocumentId(uri);
//                final String[] split = docId.split(":");
//                final String type = split[0];
//
//                if ("primary".equalsIgnoreCase(type)) {
//                    return Environment.getExternalStorageDirectory() + "/" + split[1];
//                }
//            }
//            // DownloadsProvider
//            else if (isDownloadsDocument(uri)) {
//                final String id = DocumentsContract.getDocumentId(uri);
//                final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
//                return getDataColumn(context, contentUri, null, null);
//            }
        // MediaProvider
//            else
        if (isMediaDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];

            Uri contentUri = null;
            if ("image".equals(type)) {
                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            }

            final String selection = "_id=?";
            final String[] selectionArgs = new String[]{split[1]};

            return getDataColumn(context, contentUri, selection, selectionArgs);
        }
    }
    // Media
    else if ("content".equalsIgnoreCase(uri.getScheme())) {
        return getDataColumn(context, uri, null, null);
    }
    // File
    else if ("file".equalsIgnoreCase(uri.getScheme())) {
        return uri.getPath();
    }
    return null;
}


    //获取数据列_获取此 Uri 的数据列的值。这对MediaStore Uris 和其他基于文件的 ContentProvider。
    public String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {column};

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
            if (cursor != null && cursor.moveToFirst()) {
                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }


    //是否为外部存储文件
//    public boolean isExternalStorageDocument(Uri uri) {
//        return "com.android.externalstorage.documents".equals(uri.getAuthority());
//    }
//
//    //是否为下载文件
//    public boolean isDownloadsDocument(Uri uri) {
//        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
//    }

    //是否为媒体文件
    public boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        ContentResolver resolver = getContentResolver();
        switch (requestCode) {
            case PHOTO_REQUEST:
                Uri originalUri = intent.getData(); //1.获得图片的真实路径
                Bitmap bitmap = null;
                try {
                    bitmap = BitmapFactory.decodeStream(resolver.openInputStream(originalUri));//2.解码图片
                } catch (FileNotFoundException e) {
                    Log.d(TAG, "onActivityResult: get file_exception");
                    e.printStackTrace();
                }

                if (bitmap != null) {
                    //3.根据Bitmap对象创建ImageSpan对象
                    Log.d(TAG, "onActivityResult: bitmap is not null");
                    ImageSpan imageSpan = new ImageSpan(NoteEditActivity.this, bitmap);
                    String path = getPath(this, originalUri);
                    //4.使用[local][/local]将path括起来,用于之后方便识别图片路径在note中的位置
                    String img_fragment = "[local]" + path + "[/local]";
                    //创建一个SpannableString对象,以便插入用ImageSpan对象封装的图像
                    SpannableString spannableString = new SpannableString(img_fragment);
                    spannableString.setSpan(imageSpan, 0, img_fragment.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    //5.将选择的图片追加到EditText中光标所在位置
                    NoteEditText e = (NoteEditText) findViewById(R.id.note_edit_view);
                    int index = e.getSelectionStart(); //获取光标所在位置
                    Log.d(TAG, "Index是: " + index);
                    Editable edit_text = e.getEditableText();
                    edit_text.insert(index, spannableString); //将图片插入到光标所在位置

                    mWorkingNote.mContent = e.getText().toString();
                    //6.把改动提交到数据库中,两个数据库表都要改的
                    ContentResolver contentResolver = getContentResolver();
                    ContentValues contentValues = new ContentValues();
                    final long id = mWorkingNote.getNoteId();
                    contentValues.put("snippet", mWorkingNote.mContent);
                    contentResolver.update(Uri.parse("content://micode_notes/note"), contentValues, "_id=?", new String[]{"" + id});
                    ContentValues contentValues1 = new ContentValues();
                    contentValues1.put("content", mWorkingNote.mContent);
                    contentResolver.update(Uri.parse("content://micode_notes/data"), contentValues1, "mime_type=? and note_id=?", new String[]{"vnd.android.cursor.item/text_note", "" + id});

                } else {
                    Toast.makeText(NoteEditActivity.this, "获取图片失败", Toast.LENGTH_SHORT).show();
                }
                break;
            default:
                break;
        }
    }
    //

注意:

4.加入方法convertToImage()(路径:MiNotes\app\src\main\java\net\micode\notes\ui\NoteEditActivity.java)

private void convertToImage() {
    NoteEditText noteEditText = (NoteEditText) findViewById(R.id.note_edit_view); //获取当前的edit
    Editable editable = noteEditText.getText();//1.获取text
    String noteText = editable.toString(); //2.将note内容转换为字符串
    int length = editable.length(); //内容的长度
    //3.截取img片段 [local]+uri+[local],提取uri
    for(int i = 0; i < length; i++) {
        for(int j = i; j < length; j++) {
            String img_fragment = noteText.substring(i, j+1); //img_fragment:关于图片路径的片段
            if(img_fragment.length() > 15 && img_fragment.endsWith("[/local]") && img_fragment.startsWith("[local]")){
                int limit = 7;  //[local]为7个字符
                //[local][/local]共15个字符,剩下的为真正的path长度
                int len = img_fragment.length()-15;
                //从[local]之后的len个字符就是path
                String path = img_fragment.substring(limit,limit+len);//获取到了图片路径
                Bitmap bitmap = null;
                Log.d(TAG, "图片的路径是:"+path);
                try {
                    bitmap = BitmapFactory.decodeFile(path);//将图片路径解码为图片格式
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if(bitmap!=null){  //若图片存在
                    Log.d(TAG, "图片不为null");
                    ImageSpan imageSpan = new ImageSpan(NoteEditActivity.this, bitmap);
                    //4.创建一个SpannableString对象,以便插入用ImageSpan对象封装的图像
                    String ss = "[local]" + path + "[/local]";
                    SpannableString spannableString = new SpannableString(ss);
                    //5.将指定的标记对象附加到文本的开始...结束范围
                    spannableString.setSpan(imageSpan, 0, ss.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    Log.d(TAG, "Create spannable string success!");
                    Editable edit_text = noteEditText.getEditableText();
                    edit_text.delete(i,i+len+15); //6.删掉图片路径的文字
                    edit_text.insert(i, spannableString); //7.在路径的起始位置插入图片
                }
            }
        }
    }
}

最后一步:这里有一个小细节,就是导入的图片会变成路径,我们需要调用convertToImage()函数,在,onCheckListModeChanged()和initNoteScreen()中加入convertToImage()的调用,如下图(可以双击Shift来找到相应的位置方便添加)

(路径:MiNotes\app\src\main\java\net\micode\notes\ui\NoteEditActivity.java)

1,在onCheckListModeChanged(),加入:

2.在initNoteScreen中加入调用

标签:便签,String,img,--,uri,软件工程,null,local,final
From: https://blog.csdn.net/weixin_73164943/article/details/139282837

相关文章

  • PyTorch学习(8):PyTorch中Tensor的合并于拆分(torch.cat, torch.stack, torch.trunk, tor
    1.写在前面       在使用PyTorch执行深度学习开发时,经常会用到对Tensor的合并于拆分操作。如我们在使用CSP时,有时候会需要将Tensor拆分成两部分,其中一部分进行进行CrossStage操作,另一部分执行多重卷积操作,这个时候我们就会用到四个典型的接口,分别是torch.cat,torch......
  • 制作dolphinscheduler+spark+hadoop镜像
    项目需要在ds中执行spark集群任务,并且交付方式是提供一个镜像,所以要把这3者做成一个镜像配置进行相应配置。 1.准备基础镜像有大神已经制作好了spark+hadoop镜像,参考链接:https://zhuanlan.zhihu.com/p/421375012我们下载此镜像dockerpulls1mplecc/spark-hadoop:3然后准......
  • 夏天时家里的空气开关总是频繁跳闸——原因——排除大功率问题
    参考:https://baike.baidu.com/item/空气开关/1606177?fr=ge_ala一般认为空气开关跳闸是因为电流过大,导致磁力增加,然后跳闸,但是我这平时用电总是持平的,为什么最近就开始跳闸呢。最近的唯一的变化就是天气热了,空气开关的盒子本身盖的比较紧,没有什么可通风的,这下天气一热,就导致......
  • YOLOv10(1):初探,训练自己的数据
    目录1.写在前面2.值得关注的点3.训练自己的数据集4.阅读代码的小建议1.写在前面        很多人YOLOv9还没有完全研究透,YOLOv10出来了。        惊不惊喜,意不意外!        据论文里提到,YOLOv10就是为了加速推理,在保证精度的同时,降低参数......
  • 三十二、openlayers官网示例解析Draw lines rendered with WebGL——使用WebGL动态修
     官网demo地址:DrawlinesrenderedwithWebGL这个示例展示了如何用webgl渲染矢量图形并动态修改点、线属性。首先先把基本的地图加载上去initMap(){this.map=newMap({layers:[newTileLayer({source:newXYZ({......
  • JavaDS-学习数据结构之如果从零开始手搓顺序表,顺带学习自定义异常怎么用!
    前言笔者开始学习数据结构了,虽然笔者已经会用了,不管是C++中的stl亦或是Java中的集合,为了算法比赛多少都突击过,但只知其然而不知其所以然,还是会限制发展的,因此,笔者写下这篇博客.内容是手搓一个顺序表.顺带加一点异常的使用,大伙看个乐子就好了.有错误直接私信喷我就......
  • WEB安全:Content Security Policy (CSP) 详解
    ContentSecurityPolicy(CSP)是一种强大的网页安全机制,用于防止跨站脚本(XSS)和其他注入攻击。通过设置一系列的内容安全策略,CSP可以限制网页可以加载的资源,从而保护用户数据和网站的安全性。什么是XSS攻击?跨站脚本攻击(XSS)是一种常见的安全漏洞,攻击者通过注......
  • 机床数据采集网关的功能与特点主要有哪些?机床数据采集网关的应用价值-天拓四方
    随着工业4.0时代的到来,机床数据采集网关成为了实现智能制造和数字化转型的重要工具。作为连接机床与上层管理系统之间的桥梁,机床数据采集网关发挥着至关重要的作用,它能够实现机床数据的实时采集、传输与处理,为企业的生产管理和决策提供有力支持。一、机床数据采集网关的功能与......
  • 物联边缘网关的部署管理及成本效益分析-天拓四方
    物联边缘网关在物联网生态系统中占据着至关重要的位置,其技术深度和广度都在不断拓展。在硬件层面,边缘网关采用了高性能的处理器和存储技术,以满足对大量数据实时处理和分析的需求。同时,为了应对复杂多变的网络环境,边缘网关还集成了多种通信接口和协议,确保数据的稳定传输和高效交......
  • Maven项目通过maven central 发布到中央仓库 https://repo.maven.apache.org/ 手把手
    一、注册mavencentral账号​https://central.sonatype.com/publishing/namespaces我这里直接使用github账号登录,可以自己注册或者直接使用google账号或者github账号登录这里github账号登录之后应该只出现io.github下面的io.gitee我也验证过所以这里出现了github......