简易安卓句分器实现

最近,我发现许多抖音用户喜欢将小说内容一句一句地发到游戏评论框中。这种行为虽然能让更多人看到这些内容,但手动复制和粘贴却是一个繁琐的过程。为了简化这一操作,我决定开发一个应用,可以一键输入大量文本,并将其根据句号、逗号和分号划分成句子。用户可以通过一个悬浮窗轻松访问上一句、当前句子和下一句,进一步简化操作。

在这个应用的开发过程中,我使用了 Android 的三个重要组件:FragmentViewModelView Binding。下面,我将详细介绍这三者的关系以及如何实现具体功能的代码。

1. Fragment

Fragment 是 Android UI 的一部分,可以被看作一个独立的界面模块。在应用中,多个 Fragment 可以在同一个 Activity 中共存,各自管理自己的 UI 和生命周期事件。在我们的应用中,HomeFragment 负责与用户交互,例如输入文本和处理按钮点击事件。

以下是 HomeFragment 的完整代码:

java 复制代码
package cn.techfanyi.ui.home;

import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;

import cn.techfanyi.databinding.FragmentHomeBinding;

public class HomeFragment extends Fragment {

    private FragmentHomeBinding binding;
    private HomeViewModel homeViewModel;

    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        // 创建ViewModel
        homeViewModel = new ViewModelProvider(this).get(HomeViewModel.class);

        // 绑定视图
        binding = FragmentHomeBinding.inflate(inflater, container, false);
        View root = binding.getRoot();

        // 获取输入框和按钮
        EditText editText = binding.editText; // 假设在XML中有一个EditText用于输入
        Button recognizeButton = binding.recognizeButton; // 假设在XML中有一个按钮用于识别
        TextView resultTextView = binding.resultTextView; // 显示结果的TextView

        // 设置按钮点击事件
        recognizeButton.setOnClickListener(v -> {
            String inputText = editText.getText().toString();
            if (TextUtils.isEmpty(inputText)) {
                Toast.makeText(getContext(), "请输入文本", Toast.LENGTH_SHORT).show();
                return;
            }

            // 将输入的文本划分为句子
            String[] sentences = inputText.split("[。;,]");
            homeViewModel.setSentences(sentences); // 将句子存储到ViewModel中

            // 更新结果文本
            resultTextView.setText(TextUtils.join("\n", sentences));
        });

        return root;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }
}

2. ViewModel

ViewModel 是 Android 架构组件,用于存储和管理与 UI 相关的数据。其主要作用是持久化数据,使其能够在 FragmentActivity 的生命周期变化(如屏幕旋转)时依然可用。在我们的应用中,HomeViewModel 用于管理文本数据和句子划分的逻辑。

以下是 HomeViewModel 的代码:

java 复制代码
package cn.techfanyi.ui.home;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

public class HomeViewModel extends ViewModel {
    private final MutableLiveData<String[]> sentences;

    public HomeViewModel() {
        sentences = new MutableLiveData<>();
    }

    // 设置句子
    public void setSentences(String[] sentencesArray) {
        sentences.setValue(sentencesArray);
    }

    // 获取句子
    public LiveData<String[]> getSentences() {
        return sentences;
    }
}

3. View Binding

View Binding 是一种更安全和高效的方式来访问 XML 布局中的视图。它会为每个 XML 布局文件生成一个绑定类,可以直接通过绑定类访问布局中的视图,而无需手动调用 findViewById()

在本应用中,假设我们的布局文件为 fragment_home.xml,以下是示例 XML 布局代码:

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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=".ui.home.HomeFragment">

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入长句子" />

    <Button
        android:id="@+id/recognizeButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="识别句子"
        app:layout_constraintTop_toBottomOf="@id/editText"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

    <TextView
        android:id="@+id/resultTextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/recognizeButton"
        android:padding="16dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

悬浮窗功能实现

悬浮窗的功能主要实现上一句、当前句子、下一句的展示与复制。为了实现这个功能,我们可以使用 WindowManager 来创建一个悬浮窗,并在其中显示相应的句子。

java 复制代码
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;

public class FloatingWindowManager {
    private Context context;
    private WindowManager windowManager;
    private View floatingView;
    private TextView previousSentenceTextView;
    private TextView currentSentenceTextView;
    private TextView nextSentenceTextView;

    public FloatingWindowManager(Context context) {
        this.context = context;
        windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        createFloatingView();
    }

    private void createFloatingView() {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        floatingView = inflater.inflate(R.layout.floating_window_layout, null);

        previousSentenceTextView = floatingView.findViewById(R.id.previousSentence);
        currentSentenceTextView = floatingView.findViewById(R.id.currentSentence);
        nextSentenceTextView = floatingView.findViewById(R.id.nextSentence);

        // 设置句子点击事件
        currentSentenceTextView.setOnClickListener(v -> {
            // 复制当前句子到剪贴板
            ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
            ClipData clip = ClipData.newPlainText("sentence", currentSentenceTextView.getText());
            clipboard.setPrimaryClip(clip);
        });

        // 添加悬浮窗
        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT);
        params.gravity = Gravity.TOP | Gravity.LEFT; // 悬浮窗的位置
        params.x = 0;
        params.y = 100;

        windowManager.addView(floatingView, params);
    }

    public void updateSentences(String[] sentences, int currentIndex) {
        if (currentIndex > 0) {
            previousSentenceTextView.setText(sentences[currentIndex - 1]);
        }
        currentSentenceTextView.setText(sentences[currentIndex]);
        if (currentIndex < sentences.length - 1) {
            nextSentenceTextView.setText(sentences[currentIndex + 1]);
        }
    }
}

关系及绑定

在应用中,FragmentViewModelView Binding 之间的关系如下:

  • Fragment :负责管理 UI 和用户交互逻辑,通过 ViewModel 获取和存储数据,使用 View Binding 直接访问布局中的视图。
  • ViewModel:负责存储和管理与 UI 相关的数据,确保数据在生命周期变化时的持久性。
  • View Binding:简化了视图的访问,提高了代码的安全性和可读性。

总结

通过使用 FragmentViewModelView Binding,我们可以创建一个简化小说内容分享的应用。应用不仅提升了用户体验

,同时也展示了 Android 开发中这三者之间的紧密关系。希望这篇博客能够为你的 Android 开发之路提供一些启示!

相关推荐
逍遥德几秒前
Java编程高频的“踩坑点”-01:fastjson.JSON 转换时泛型擦除问题
java·spring boot·spring·系统架构·json
ch.ju1 分钟前
Java程序设计(第3版)第四章——类的组成
java·开发语言
我命由我123451 分钟前
PHP - PHP 基本随机数生成函数
开发语言·ide·后端·java-ee·php·intellij-idea·intellij idea
博.闻广见3 分钟前
AI_Python基础-4.标准库与IO
开发语言·python
星轨zb3 分钟前
Spring Data Redis 实战避坑:搞定序列化乱码与 Hash 结构存储
java·redis·spring·lock
吃好睡好便好4 分钟前
在Matlab中绘制质点运动轨迹图
开发语言·学习·算法·matlab·信息可视化
艾莉丝努力练剑4 分钟前
【Linux网络】Linux 网络编程:HTTP(四)从手写服务器到生产级 Nginx 与 cpp-httplib 实战
linux·运维·服务器·网络·c++·nginx·http
richard_yuu4 分钟前
C#开发全景概述:从零读懂C#的定位、优势与完整技术体系
开发语言·c#
吴声子夜歌4 分钟前
Java——线程的中断
java·中断
吴声子夜歌4 分钟前
状态机——SpringStateMachine嵌套状态流转
java·状态机·嵌套状态