简易安卓句分器实现


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

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

1. Fragment

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

以下是 HomeFragment 的完整代码:

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 .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;
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.

2. ViewModel

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

以下是 HomeViewModel 的代码:

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;
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

3. View Binding

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

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

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http:///apk/res/android"
    xmlns:app="http:///apk/res-auto"
    xmlns:tools="http:///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>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.

悬浮窗功能实现

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

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(.previousSentence);
        currentSentenceTextView = floatingView.findViewById(.currentSentence);
        nextSentenceTextView = floatingView.findViewById(.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.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]);
        }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.

关系及绑定

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

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

总结

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

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


posted @ 2024-11-26 16:17  繁依Fanyi  阅读(6)  评论(0)    收藏  举报  来源