mirror of
https://github.com/fankes/termux-app.git
synced 2025-09-06 02:35:19 +08:00
Added: Add TextIOActivity and TextIOInfo
The `TextIOActivity` can be used to edit or view text based on various config options defined by `TextIOInfo` and supports `monospace` font and horizontal scrolling for editing scripts, etc. Current max text limit is `95KB`, which can be increased in future.
This commit is contained in:
@@ -9,6 +9,7 @@ android {
|
||||
implementation "androidx.annotation:annotation:1.2.0"
|
||||
implementation "androidx.core:core:1.6.0-rc01"
|
||||
implementation "androidx.window:window:1.0.0-alpha09"
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
implementation "com.google.guava:guava:24.1-jre"
|
||||
implementation "io.noties.markwon:core:$markwonVersion"
|
||||
implementation "io.noties.markwon:ext-strikethrough:$markwonVersion"
|
||||
|
@@ -0,0 +1,278 @@
|
||||
package com.termux.shared.activities;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.InputFilter;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import android.widget.HorizontalScrollView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
import com.termux.shared.interact.ShareUtils;
|
||||
import com.termux.shared.logger.Logger;
|
||||
import com.termux.shared.R;
|
||||
import com.termux.shared.models.TextIOInfo;
|
||||
import com.termux.shared.view.KeyboardUtils;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* An activity to edit or view text based on config passed as {@link TextIOInfo}.
|
||||
*
|
||||
* Add Following to `AndroidManifest.xml` to use in an app:
|
||||
*
|
||||
* {@code ` <activity android:name="com.termux.shared.activities.TextIOActivity" android:theme="@style/Theme.AppCompat.TermuxTextIOActivity" />` }
|
||||
*/
|
||||
public class TextIOActivity extends AppCompatActivity {
|
||||
|
||||
private static final String CLASS_NAME = ReportActivity.class.getCanonicalName();
|
||||
public static final String EXTRA_TEXT_IO_INFO_OBJECT = CLASS_NAME + ".EXTRA_TEXT_IO_INFO_OBJECT";
|
||||
|
||||
private TextView mTextIOLabel;
|
||||
private View mTextIOLabelSeparator;
|
||||
private EditText mTextIOText;
|
||||
private HorizontalScrollView mTextIOHorizontalScrollView;
|
||||
private LinearLayout mTextIOTextLinearLayout;
|
||||
private TextView mTextIOTextCharacterUsage;
|
||||
|
||||
private TextIOInfo mTextIOInfo;
|
||||
private Bundle mBundle;
|
||||
|
||||
private static final String LOG_TAG = "TextIOActivity";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
Logger.logVerbose(LOG_TAG, "onCreate");
|
||||
|
||||
setContentView(R.layout.activity_text_io);
|
||||
|
||||
mTextIOLabel = findViewById(R.id.text_io_label);
|
||||
mTextIOLabelSeparator = findViewById(R.id.text_io_label_separator);
|
||||
mTextIOText = findViewById(R.id.text_io_text);
|
||||
mTextIOHorizontalScrollView = findViewById(R.id.text_io_horizontal_scroll_view);
|
||||
mTextIOTextLinearLayout = findViewById(R.id.text_io_text_linear_layout);
|
||||
mTextIOTextCharacterUsage = findViewById(R.id.text_io_text_character_usage);
|
||||
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
if (toolbar != null) {
|
||||
setSupportActionBar(toolbar);
|
||||
}
|
||||
|
||||
mBundle = null;
|
||||
Intent intent = getIntent();
|
||||
if (intent != null)
|
||||
mBundle = intent.getExtras();
|
||||
else if (savedInstanceState != null)
|
||||
mBundle = savedInstanceState;
|
||||
|
||||
updateUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
Logger.logVerbose(LOG_TAG, "onNewIntent");
|
||||
|
||||
// Views must be re-created since different configs for isEditingTextDisabled() and
|
||||
// isHorizontallyScrollable() will not work or at least reliably
|
||||
finish();
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private void updateUI() {
|
||||
if (mBundle == null) {
|
||||
finish(); return;
|
||||
}
|
||||
|
||||
mTextIOInfo = (TextIOInfo) mBundle.getSerializable(EXTRA_TEXT_IO_INFO_OBJECT);
|
||||
if (mTextIOInfo == null) {
|
||||
finish(); return;
|
||||
}
|
||||
|
||||
final ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
if (mTextIOInfo.getTitle() != null)
|
||||
actionBar.setTitle(mTextIOInfo.getTitle());
|
||||
else
|
||||
actionBar.setTitle("Text Input");
|
||||
|
||||
if (mTextIOInfo.shouldShowBackButtonInActionBar()) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
actionBar.setDisplayShowHomeEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
mTextIOLabel.setVisibility(View.GONE);
|
||||
mTextIOLabelSeparator.setVisibility(View.GONE);
|
||||
if (mTextIOInfo.isLabelEnabled()) {
|
||||
mTextIOLabel.setVisibility(View.VISIBLE);
|
||||
mTextIOLabelSeparator.setVisibility(View.VISIBLE);
|
||||
mTextIOLabel.setText(mTextIOInfo.getLabel());
|
||||
mTextIOLabel.setFilters(new InputFilter[] { new InputFilter.LengthFilter(TextIOInfo.LABEL_SIZE_LIMIT_IN_BYTES) });
|
||||
mTextIOLabel.setTextSize(mTextIOInfo.getLabelSize());
|
||||
mTextIOLabel.setTextColor(mTextIOInfo.getLabelColor());
|
||||
mTextIOLabel.setTypeface(Typeface.create(mTextIOInfo.getLabelTypeFaceFamily(), mTextIOInfo.getLabelTypeFaceStyle()));
|
||||
}
|
||||
|
||||
|
||||
if (mTextIOInfo.isHorizontallyScrollable()) {
|
||||
mTextIOHorizontalScrollView.setEnabled(true);
|
||||
mTextIOText.setHorizontallyScrolling(true);
|
||||
} else {
|
||||
// Remove mTextIOHorizontalScrollView and add mTextIOText in its place
|
||||
ViewGroup parent = (ViewGroup) mTextIOHorizontalScrollView.getParent();
|
||||
if (parent != null && parent.indexOfChild(mTextIOText) < 0) {
|
||||
ViewGroup.LayoutParams params = mTextIOHorizontalScrollView.getLayoutParams();
|
||||
int index = parent.indexOfChild(mTextIOHorizontalScrollView);
|
||||
mTextIOTextLinearLayout.removeAllViews();
|
||||
mTextIOHorizontalScrollView.removeAllViews();
|
||||
parent.removeView(mTextIOHorizontalScrollView);
|
||||
parent.addView(mTextIOText, index, params);
|
||||
mTextIOText.setHorizontallyScrolling(false);
|
||||
}
|
||||
}
|
||||
|
||||
mTextIOText.setText(mTextIOInfo.getText());
|
||||
mTextIOText.setFilters(new InputFilter[] { new InputFilter.LengthFilter(mTextIOInfo.getTextLengthLimit()) });
|
||||
mTextIOText.setTextSize(mTextIOInfo.getTextSize());
|
||||
mTextIOText.setTextColor(mTextIOInfo.getTextColor());
|
||||
mTextIOText.setTypeface(Typeface.create(mTextIOInfo.getTextTypeFaceFamily(), mTextIOInfo.getTextTypeFaceStyle()));
|
||||
|
||||
// setTextIsSelectable must be called after changing KeyListener to regain focusability and selectivity
|
||||
if (mTextIOInfo.isEditingTextDisabled()) {
|
||||
mTextIOText.setCursorVisible(false);
|
||||
mTextIOText.setKeyListener(null);
|
||||
mTextIOText.setTextIsSelectable(true);
|
||||
}
|
||||
|
||||
if (mTextIOInfo.shouldShowTextCharacterUsage()) {
|
||||
mTextIOTextCharacterUsage.setVisibility(View.VISIBLE);
|
||||
updateTextIOTextCharacterUsage(mTextIOInfo.getText());
|
||||
|
||||
mTextIOText.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 editable) {
|
||||
if (editable != null)
|
||||
updateTextIOTextCharacterUsage(editable.toString());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
mTextIOTextCharacterUsage.setVisibility(View.GONE);
|
||||
mTextIOText.addTextChangedListener(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTextIOInfoText() {
|
||||
if (mTextIOText != null)
|
||||
mTextIOInfo.setText(mTextIOText.getText().toString());
|
||||
}
|
||||
|
||||
private void updateTextIOTextCharacterUsage(String text) {
|
||||
if (text == null) text = "";
|
||||
if (mTextIOTextCharacterUsage != null)
|
||||
mTextIOTextCharacterUsage.setText(String.format(Locale.getDefault(), "%1$d/%2$d", text.length(), mTextIOInfo.getTextLengthLimit()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
updateTextIOInfoText();
|
||||
outState.putSerializable(EXTRA_TEXT_IO_INFO_OBJECT, mTextIOInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(final Menu menu) {
|
||||
final MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.menu_text_io, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||
String text = "";
|
||||
if (mTextIOText != null)
|
||||
text = mTextIOText.getText().toString();
|
||||
|
||||
int id = item.getItemId();
|
||||
if (id == android.R.id.home) {
|
||||
confirm();
|
||||
} if (id == R.id.menu_item_cancel) {
|
||||
cancel();
|
||||
} else if (id == R.id.menu_item_share_text) {
|
||||
ShareUtils.shareText(this, mTextIOInfo.getTitle(), text);
|
||||
} else if (id == R.id.menu_item_copy_text) {
|
||||
ShareUtils.copyTextToClipboard(this, text, null);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
confirm();
|
||||
}
|
||||
|
||||
/** Confirm current text and send it back to calling {@link Activity}. */
|
||||
private void confirm() {
|
||||
updateTextIOInfoText();
|
||||
KeyboardUtils.hideSoftKeyboard(this, mTextIOText);
|
||||
setResult(Activity.RESULT_OK, getResultIntent());
|
||||
finish();
|
||||
}
|
||||
|
||||
/** Cancel current text and notify calling {@link Activity}. */
|
||||
private void cancel() {
|
||||
KeyboardUtils.hideSoftKeyboard(this, mTextIOText);
|
||||
setResult(Activity.RESULT_CANCELED, getResultIntent());
|
||||
finish();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Intent getResultIntent() {
|
||||
Intent intent = new Intent();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable(EXTRA_TEXT_IO_INFO_OBJECT, mTextIOInfo);
|
||||
intent.putExtras(bundle);
|
||||
return intent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link Intent} that can be used to start the {@link TextIOActivity}.
|
||||
*
|
||||
* @param context The {@link Context} for operations.
|
||||
* @param textIOInfo The {@link TextIOInfo} containing info for the edit text.
|
||||
*/
|
||||
public static Intent newInstance(@NonNull final Context context, @NonNull final TextIOInfo textIOInfo) {
|
||||
Intent intent = new Intent(context, TextIOActivity.class);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable(EXTRA_TEXT_IO_INFO_OBJECT, textIOInfo);
|
||||
intent.putExtras(bundle);
|
||||
return intent;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,234 @@
|
||||
package com.termux.shared.models;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.termux.shared.activities.TextIOActivity;
|
||||
import com.termux.shared.data.DataUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* An object that stored info for {@link TextIOActivity}.
|
||||
* Max text limit is 95KB to prevent TransactionTooLargeException as per
|
||||
* {@link DataUtils#TRANSACTION_SIZE_LIMIT_IN_BYTES}. Larger size can be supported for in-app
|
||||
* transactions by storing {@link TextIOInfo} as a serialized object in a file like
|
||||
* {@link com.termux.shared.activities.ReportActivity} does.
|
||||
*/
|
||||
public class TextIOInfo implements Serializable {
|
||||
|
||||
public static final int GENERAL_DATA_SIZE_LIMIT_IN_BYTES = 1000;
|
||||
public static final int LABEL_SIZE_LIMIT_IN_BYTES = 4000;
|
||||
public static final int TEXT_SIZE_LIMIT_IN_BYTES = 100000 - GENERAL_DATA_SIZE_LIMIT_IN_BYTES - LABEL_SIZE_LIMIT_IN_BYTES; // < 100KB
|
||||
|
||||
/** The action for which {@link TextIOActivity} will be started. */
|
||||
private final String mAction;
|
||||
/** The internal app component that is will start the {@link TextIOActivity}. */
|
||||
private final String mSender;
|
||||
|
||||
/** The activity title. */
|
||||
private String mTitle;
|
||||
|
||||
/** If back button should be shown in {@link android.app.ActionBar}. */
|
||||
private boolean mShowBackButtonInActionBar = false;
|
||||
|
||||
|
||||
/** If label is enabled. */
|
||||
private boolean mLabelEnabled = false;
|
||||
/**
|
||||
* The label of text input set in {@link android.widget.TextView} that can be updated by user.
|
||||
* Max allowed length is {@link #LABEL_SIZE_LIMIT_IN_BYTES}.
|
||||
*/
|
||||
private String mLabel;
|
||||
/** The text size of label. Defaults to 14sp. */
|
||||
private int mLabelSize = 14;
|
||||
/** The text color of label. Defaults to {@link Color#BLACK}. */
|
||||
private int mLabelColor = Color.BLACK;
|
||||
/** The {@link Typeface} family of label. Defaults to "sans-serif". */
|
||||
private String mLabelTypeFaceFamily = "sans-serif";
|
||||
/** The {@link Typeface} style of label. Defaults to {@link Typeface#BOLD}. */
|
||||
private int mLabelTypeFaceStyle = Typeface.BOLD;
|
||||
|
||||
|
||||
/**
|
||||
* The text of text input set in {@link android.widget.EditText} that can be updated by user.
|
||||
* Max allowed length is {@link #TEXT_SIZE_LIMIT_IN_BYTES}.
|
||||
*/
|
||||
private String mText;
|
||||
/** The text size for text. Defaults to 12sp. */
|
||||
private int mTextSize = 12;
|
||||
/** The text size for text. Defaults to {@link #TEXT_SIZE_LIMIT_IN_BYTES}. */
|
||||
private int mTextLengthLimit = TEXT_SIZE_LIMIT_IN_BYTES;
|
||||
/** The text color of text. Defaults to {@link Color#BLACK}. */
|
||||
private int mTextColor = Color.BLACK;
|
||||
/** The {@link Typeface} family for text. Defaults to "sans-serif". */
|
||||
private String mTextTypeFaceFamily = "sans-serif";
|
||||
/** The {@link Typeface} style for text. Defaults to {@link Typeface#NORMAL}. */
|
||||
private int mTextTypeFaceStyle = Typeface.NORMAL;
|
||||
/** If horizontal scrolling should be enabled for text. */
|
||||
private boolean mTextHorizontallyScrolling = false;
|
||||
/** If character usage should be enabled for text. */
|
||||
private boolean mShowTextCharacterUsage = false;
|
||||
/** If editing text should be disabled so that text acts like its in a {@link android.widget.TextView}. */
|
||||
private boolean mEditingTextDisabled = false;
|
||||
|
||||
|
||||
public TextIOInfo(@NonNull String action, @NonNull String sender) {
|
||||
mAction = action;
|
||||
mSender = sender;
|
||||
}
|
||||
|
||||
|
||||
public String getAction() {
|
||||
return mAction;
|
||||
}
|
||||
|
||||
public String getSender() {
|
||||
return mSender;
|
||||
}
|
||||
|
||||
|
||||
public String getTitle() {
|
||||
return mTitle;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
mTitle = title;
|
||||
}
|
||||
|
||||
public boolean shouldShowBackButtonInActionBar() {
|
||||
return mShowBackButtonInActionBar;
|
||||
}
|
||||
|
||||
public void setShowBackButtonInActionBar(boolean showBackButtonInActionBar) {
|
||||
mShowBackButtonInActionBar = showBackButtonInActionBar;
|
||||
}
|
||||
|
||||
|
||||
public boolean isLabelEnabled() {
|
||||
return mLabelEnabled;
|
||||
}
|
||||
|
||||
public void setLabelEnabled(boolean labelEnabled) {
|
||||
mLabelEnabled = labelEnabled;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
public void setLabel(String label) {
|
||||
mLabel = DataUtils.getTruncatedCommandOutput(label, LABEL_SIZE_LIMIT_IN_BYTES, true, false, false);
|
||||
}
|
||||
|
||||
public int getLabelSize() {
|
||||
return mLabelSize;
|
||||
}
|
||||
|
||||
public void setLabelSize(int labelSize) {
|
||||
if (labelSize > 0)
|
||||
mLabelSize = labelSize;
|
||||
}
|
||||
|
||||
public int getLabelColor() {
|
||||
return mLabelColor;
|
||||
}
|
||||
|
||||
public void setLabelColor(int labelColor) {
|
||||
mLabelColor = labelColor;
|
||||
}
|
||||
|
||||
public String getLabelTypeFaceFamily() {
|
||||
return mLabelTypeFaceFamily;
|
||||
}
|
||||
|
||||
public void setLabelTypeFaceFamily(String labelTypeFaceFamily) {
|
||||
mLabelTypeFaceFamily = labelTypeFaceFamily;
|
||||
}
|
||||
|
||||
public int getLabelTypeFaceStyle() {
|
||||
return mLabelTypeFaceStyle;
|
||||
}
|
||||
|
||||
public void setLabelTypeFaceStyle(int labelTypeFaceStyle) {
|
||||
mLabelTypeFaceStyle = labelTypeFaceStyle;
|
||||
}
|
||||
|
||||
|
||||
public String getText() {
|
||||
return mText;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
mText = DataUtils.getTruncatedCommandOutput(text, TEXT_SIZE_LIMIT_IN_BYTES, true, false, false);
|
||||
}
|
||||
|
||||
public int getTextSize() {
|
||||
return mTextSize;
|
||||
}
|
||||
|
||||
public void setTextSize(int textSize) {
|
||||
if (textSize > 0)
|
||||
mTextSize = textSize;
|
||||
}
|
||||
|
||||
public int getTextLengthLimit() {
|
||||
return mTextLengthLimit;
|
||||
}
|
||||
|
||||
public void setTextLengthLimit(int textLengthLimit) {
|
||||
if (textLengthLimit < TEXT_SIZE_LIMIT_IN_BYTES)
|
||||
mTextLengthLimit = textLengthLimit;
|
||||
}
|
||||
|
||||
public int getTextColor() {
|
||||
return mTextColor;
|
||||
}
|
||||
|
||||
public void setTextColor(int textColor) {
|
||||
mTextColor = textColor;
|
||||
}
|
||||
|
||||
public String getTextTypeFaceFamily() {
|
||||
return mTextTypeFaceFamily;
|
||||
}
|
||||
|
||||
public void setTextTypeFaceFamily(String textTypeFaceFamily) {
|
||||
mTextTypeFaceFamily = textTypeFaceFamily;
|
||||
}
|
||||
|
||||
public int getTextTypeFaceStyle() {
|
||||
return mTextTypeFaceStyle;
|
||||
}
|
||||
|
||||
public void setTextTypeFaceStyle(int textTypeFaceStyle) {
|
||||
mTextTypeFaceStyle = textTypeFaceStyle;
|
||||
}
|
||||
|
||||
public boolean isHorizontallyScrollable() {
|
||||
return mTextHorizontallyScrolling;
|
||||
}
|
||||
|
||||
public void setTextHorizontallyScrolling(boolean textHorizontallyScrolling) {
|
||||
mTextHorizontallyScrolling = textHorizontallyScrolling;
|
||||
}
|
||||
|
||||
public boolean shouldShowTextCharacterUsage() {
|
||||
return mShowTextCharacterUsage;
|
||||
}
|
||||
|
||||
public void setShowTextCharacterUsage(boolean showTextCharacterUsage) {
|
||||
mShowTextCharacterUsage = showTextCharacterUsage;
|
||||
}
|
||||
|
||||
public boolean isEditingTextDisabled() {
|
||||
return mEditingTextDisabled;
|
||||
}
|
||||
|
||||
public void setEditingTextDisabled(boolean editingTextDisabled) {
|
||||
mEditingTextDisabled = editingTextDisabled;
|
||||
}
|
||||
|
||||
}
|
93
termux-shared/src/main/res/layout/activity_text_io.xml
Normal file
93
termux-shared/src/main/res/layout/activity_text_io.xml
Normal file
@@ -0,0 +1,93 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include
|
||||
layout="@layout/partial_toolbar"
|
||||
android:id="@+id/partial_toolbar"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_io_label"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/content_padding"
|
||||
android:gravity="start|center_vertical"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@android:color/black"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<View
|
||||
android:id="@+id/text_io_label_separator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginHorizontal="@dimen/content_padding"
|
||||
android:background="@android:color/darker_gray"
|
||||
android:visibility="invisible" />
|
||||
|
||||
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<!-- id must be assigned to scroll views to restore scroll position automatically on activity resume -->
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/text_io_nested_scroll_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:padding="@dimen/content_padding_half"
|
||||
android:fillViewport="true"
|
||||
app:layout_constraintBottom_toTopOf="@+id/text_io_text_character_usage"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/text_io_horizontal_scroll_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/text_io_text_linear_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/text_io_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="start|top"
|
||||
android:inputType="textMultiLine"
|
||||
android:importantForAutofill="no"
|
||||
tools:ignore="LabelFor" />
|
||||
</LinearLayout>
|
||||
|
||||
</HorizontalScrollView>
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_io_text_character_usage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingEnd="@dimen/content_padding_half"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:gravity="end|center_vertical"
|
||||
android:textSize="12sp"
|
||||
android:textColor="@android:color/black"
|
||||
android:visibility="invisible" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</LinearLayout>
|
20
termux-shared/src/main/res/menu/menu_text_io.xml
Normal file
20
termux-shared/src/main/res/menu/menu_text_io.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_item_cancel"
|
||||
android:title="@string/action_cancel"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/menu_item_share_text"
|
||||
android:icon="@drawable/ic_share"
|
||||
android:title="@string/action_share"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/menu_item_copy_text"
|
||||
android:icon="@drawable/ic_copy"
|
||||
android:title="@string/action_copy"
|
||||
app:showAsAction="never" />
|
||||
|
||||
</menu>
|
@@ -33,9 +33,6 @@
|
||||
|
||||
|
||||
<!-- ReportActivity -->
|
||||
<string name="action_copy">Copy</string>
|
||||
<string name="action_share">Share</string>
|
||||
<string name="action_save_to_file">Save To File</string>
|
||||
<string name="title_report_text">Report Text</string>
|
||||
<string name="msg_report_truncated">**Report Truncated**\n\nReport is too large to view here.
|
||||
Use `Save To File` option from options menu (3-dots on top right) and view it in an external text editor app.\n\n##\n\n</string>
|
||||
@@ -87,6 +84,10 @@
|
||||
<!-- Miscellaneous -->
|
||||
<string name="action_yes">Yes</string>
|
||||
<string name="action_no">No</string>
|
||||
<string name="action_copy">Copy</string>
|
||||
<string name="action_share">Share</string>
|
||||
<string name="action_cancel">Cancel</string>
|
||||
<string name="action_save_to_file">Save To File</string>
|
||||
|
||||
|
||||
|
||||
|
@@ -4,6 +4,10 @@
|
||||
<item name="colorPrimaryDark">#FF0000</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.AppCompat.TermuxTextIOActivity" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<item name="colorPrimaryDark">#FF0000</item>
|
||||
</style>
|
||||
|
||||
<style name="Toolbar.Title" parent="TextAppearance.Widget.AppCompat.Toolbar.Title">
|
||||
<item name="android:textSize">14sp</item>
|
||||
</style>
|
||||
|
Reference in New Issue
Block a user