Compare commits

...

11 Commits

Author SHA1 Message Date
28ecc605e1 <winboll>APK 15.11.26 release Publish. 2026-04-30 12:07:31 +08:00
523a8e49e0 更新一下属性命名,清理冗余代码。 2026-04-30 12:03:37 +08:00
59a9e0ee45 添加TermuxButton按钮控件类 2026-04-30 11:48:27 +08:00
cbf1341435 添加TermuxButtonModel数据模型 2026-04-30 10:57:34 +08:00
dadf573675 改进Termux应用调用函数,添加TermuxWorkSpaces按钮响应。 2026-04-30 10:42:50 +08:00
7420a5cd48 添加TermuxWorkSpaces按钮视图 2026-04-30 10:14:27 +08:00
dc6a589db4 调整UI布局 2026-04-30 10:09:12 +08:00
e3f47043ef 更新Termux应用打开方法 2026-04-30 09:58:50 +08:00
a825951aad feat: 在 MyTermuxActivity 中添加 Termux 按钮功能
- 在 activity_my_termux.xml 布局中添加 Termux 按钮(底部居中)
- 在 MyTermuxActivity.java 中实现按钮点击事件
- 调用 TermuxCommandExecutor 执行 Termux 命令
- 移除了空 FrameLayout,简化布局结构
2026-04-30 09:42:08 +08:00
79cb841349 feat: 添加 MyTermuxActivity 菜单及工具栏功能
- MainActivity 添加 MyTermuxActivity 菜单项
- 配置 MyTermuxActivity 注册到 AndroidManifest.xml
- 添加 Toolbar 布局并初始化工具栏
- 设置一级标题应用名称、二级标题活动名称
- 添加返回按钮导航逻辑

修改文件:MainActivity.java, MyTermuxActivity.java, activity_my_termux.xml, toolbar_main.xml, strings.xml, AndroidManifest.xml, gradlew
2026-04-30 08:56:49 +08:00
d3c40efffa 添加我的Termux活动类 2026-04-30 08:34:29 +08:00
12 changed files with 668 additions and 23 deletions

0
gradlew vendored Normal file → Executable file
View File

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle #Created by .winboll/winboll_app_build.gradle
#Wed Apr 08 17:37:24 GMT 2026 #Thu Apr 30 12:07:31 HKT 2026
stageCount=26 stageCount=27
libraryProject= libraryProject=
baseVersion=15.11 baseVersion=15.11
publishVersion=15.11.25 publishVersion=15.11.26
buildCount=30 buildCount=0
baseBetaVersion=15.11.26 baseBetaVersion=15.11.27

View File

@@ -1,9 +1,9 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<manifest <manifest
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
package="cc.winboll.studio.winboll"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:sharedUserId="com.termux"> package="cc.winboll.studio.winboll"
android:sharedUserId="com.termux">
<!-- 拥有完全的网络访问权限 --> <!-- 拥有完全的网络访问权限 -->
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
@@ -13,11 +13,15 @@
<!-- 对正在运行的应用重新排序 --> <!-- 对正在运行的应用重新排序 -->
<uses-permission android:name="android.permission.REORDER_TASKS"/> <uses-permission android:name="android.permission.REORDER_TASKS"/>
<!-- Android 11+ 查询已安装应用权限 -->
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" <!-- 计算应用存储空间 -->
tools:ignore="QueryAllPackagesPermission" /> <uses-permission android:name="android.permission.GET_PACKAGE_SIZE"/>
<!-- 可选:兼容低版本系统 -->
<uses-permission android:name="android.permission.GET_PACKAGE_SIZE" /> <uses-permission
android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission"/>
<uses-permission android:name="android.permission.GET_PACKAGE_SIZE"/>
<application <application
android:allowBackup="true" android:allowBackup="true"
@@ -291,17 +295,23 @@
<activity android:name="cc.winboll.studio.winboll.unittest.TermuxEnvTestActivity"/> <activity android:name="cc.winboll.studio.winboll.unittest.TermuxEnvTestActivity"/>
<activity <activity
android:name=".termux.NfcTermuxBridgeActivity" android:name=".termux.NfcTermuxBridgeActivity"
android:exported="true"> <!-- 必须设置为 true允许外部应用调用 --> android:exported="true">
<!-- 接收 ACTION_BUILD 意图 --> <intent-filter>
<intent-filter>
<action android:name="cc.winboll.studio.winboll.termux.NfcTermuxBridgeActivity.ACTION_BUILD" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity> <action android:name="cc.winboll.studio.winboll.termux.NfcTermuxBridgeActivity.ACTION_BUILD"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<activity android:name="cc.winboll.studio.winboll.applications.MyTermuxActivity"
android:label="@string/my_termux_activity"
android:exported="true"/>
</application> </application>

View File

@@ -15,6 +15,7 @@ import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.winboll.R; import cc.winboll.studio.winboll.R;
import cc.winboll.studio.winboll.activities.AboutActivity; import cc.winboll.studio.winboll.activities.AboutActivity;
import cc.winboll.studio.winboll.activities.SettingsActivity; import cc.winboll.studio.winboll.activities.SettingsActivity;
import cc.winboll.studio.winboll.applications.MyTermuxActivity;
import cc.winboll.studio.winboll.fragments.BrowserFragment; import cc.winboll.studio.winboll.fragments.BrowserFragment;
import cc.winboll.studio.winboll.unittest.TermuxEnvTestActivity; import cc.winboll.studio.winboll.unittest.TermuxEnvTestActivity;
import java.util.ArrayList; import java.util.ArrayList;
@@ -155,6 +156,10 @@ public class MainActivity extends DrawerFragmentActivity {
Intent intent = new Intent(getApplicationContext(), AboutActivity.class); Intent intent = new Intent(getApplicationContext(), AboutActivity.class);
WinBoLLActivityManager.getInstance().startWinBoLLActivity(getApplicationContext(), intent, AboutActivity.class); WinBoLLActivityManager.getInstance().startWinBoLLActivity(getApplicationContext(), intent, AboutActivity.class);
} else if (nItemId == R.id.item_mytermux) {
Intent intent = new Intent(getApplicationContext(), MyTermuxActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} else if (nItemId == R.id.item_termux_env_test) { } else if (nItemId == R.id.item_termux_env_test) {
Intent intent = new Intent(getApplicationContext(), TermuxEnvTestActivity.class); Intent intent = new Intent(getApplicationContext(), TermuxEnvTestActivity.class);

View File

@@ -0,0 +1,77 @@
package cc.winboll.studio.winboll.applications;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.winboll.R;
import cc.winboll.studio.winboll.termux.TermuxCommandExecutor;
public class MyTermuxActivity extends AppCompatActivity {
public static final String TAG = "MyTermuxActivity";
private Toolbar mToolbar;
private Button mTermuxButton;
private Button mTermuxWorkSpacesButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_termux);
// 初始化工具栏
initToolbar();
// 初始化按钮
initView();
}
private void initToolbar() {
mToolbar = findViewById(R.id.toolbar);
if (mToolbar != null) {
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LogUtils.d(TAG, "点击返回按钮");
finish();
}
});
LogUtils.d(TAG, "工具栏初始化完成");
}
}
private void initView() {
mTermuxButton = findViewById(R.id.btn_termux);
if (mTermuxButton != null) {
mTermuxButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LogUtils.d(TAG, "点击 Termux 按钮");
TermuxCommandExecutor.openTermuxBash(MyTermuxActivity.this, "cd ~");
//TermuxCommandExecutor.openTermuxBash(MyTermuxActivity.this, "cd ~/TermuxWorkSpaces", "./TermuxWorkSpaces");
}
});
LogUtils.d(TAG, "Termux 按钮初始化完成");
}
mTermuxWorkSpacesButton = findViewById(R.id.btn_termuxworkspaces);
if (mTermuxWorkSpacesButton != null) {
mTermuxWorkSpacesButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LogUtils.d(TAG, "点击 TermuxWorkSpaces 按钮");
TermuxCommandExecutor.openTermuxBash(MyTermuxActivity.this, "cd ~/TermuxWorkSpaces", "./TermuxWorkSpaces");
}
});
LogUtils.d(TAG, "TermuxWorkSpaces 按钮初始化完成");
}
}
private boolean isTermuxAvailable() {
return TermuxCommandExecutor.isTermuxInstalled(this);
}
}

View File

@@ -0,0 +1,142 @@
package cc.winboll.studio.winboll.models;
import android.util.JsonReader;
import android.util.JsonWriter;
import cc.winboll.studio.libappbase.BaseBean;
import java.io.IOException;
/**
* @Author 豆包&ZhanGSKen<zhangsken@qq.com>
* @Date 2026/04/30 10:47
*/
public class TermuxButtonModel extends BaseBean {
public static final String TAG = "TermuxButtonModel";
String buttonName;
String exeCommand;
String workDir;
// 已修改isCommit 改为规范过去式命名 isCommitted
boolean isCommitted;
String commitTitle;
String commitInfo;
public TermuxButtonModel() {
this.buttonName = "";
this.exeCommand = "";
this.workDir = "";
// 默认初始化
this.isCommitted = false;
this.commitTitle = "";
this.commitInfo = "";
}
public void setButtonName(String buttonName) {
this.buttonName = buttonName;
}
public String getButtonName() {
return buttonName;
}
public void setExeCommand(String exeCommand) {
this.exeCommand = exeCommand;
}
public String getExeCommand() {
return exeCommand;
}
public void setWorkDir(String workDir) {
this.workDir = workDir;
}
public String getWorkDir() {
return workDir;
}
// ========== 已修改 对应 isCommitted 完整 Get & Set ==========
public boolean isCommitted() {
return isCommitted;
}
public void setCommitted(boolean committed) {
isCommitted = committed;
}
public String getCommitTitle() {
return commitTitle;
}
public void setCommitTitle(String commitTitle) {
this.commitTitle = commitTitle;
}
public String getCommitInfo() {
return commitInfo;
}
public void setCommitInfo(String commitInfo) {
this.commitInfo = commitInfo;
}
@Override
public String getName() {
return TermuxButtonModel.class.getName();
}
@Override
public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
super.writeThisToJsonWriter(jsonWriter);
jsonWriter.name("buttonName").value(getButtonName());
jsonWriter.name("exeCommand").value(getExeCommand());
jsonWriter.name("workDir").value(getWorkDir());
// JSON写入同步修改
jsonWriter.name("isCommitted").value(isCommitted());
jsonWriter.name("commitTitle").value(getCommitTitle());
jsonWriter.name("commitInfo").value(getCommitInfo());
}
@Override
public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
if (super.initObjectsFromJsonReader(jsonReader, name)) {
return true;
} else {
if (name.equals("buttonName")) {
setButtonName(jsonReader.nextString());
} else if (name.equals("exeCommand")) {
setExeCommand(jsonReader.nextString());
} else if (name.equals("workDir")) {
setWorkDir(jsonReader.nextString());
}
// JSON解析字段同步修改
else if (name.equals("isCommitted")) {
setCommitted(jsonReader.nextBoolean());
} else if (name.equals("commitTitle")) {
setCommitTitle(jsonReader.nextString());
} else if (name.equals("commitInfo")) {
setCommitInfo(jsonReader.nextString());
} else {
return false;
}
}
return true;
}
@Override
public BaseBean readBeanFromJsonReader(JsonReader jsonReader) throws IOException {
jsonReader.beginObject();
while (jsonReader.hasNext()) {
String name = jsonReader.nextName();
if (!initObjectsFromJsonReader(jsonReader, name)) {
jsonReader.skipValue();
}
}
jsonReader.endObject();
return this;
}
}

View File

@@ -22,6 +22,7 @@ public class TermuxCommandExecutor {
// Termux RunCommandService 完整类名(包名+类名) // Termux RunCommandService 完整类名(包名+类名)
private static final String TERMUX_RUN_CMD_SERVICE_CLASS = "com.termux.app.RunCommandService"; private static final String TERMUX_RUN_CMD_SERVICE_CLASS = "com.termux.app.RunCommandService";
private static final String TERMUX_RUN_CMD_ACTION = TermuxConstants.TERMUX_APP.RUN_COMMAND_SERVICE.ACTION_RUN_COMMAND; private static final String TERMUX_RUN_CMD_ACTION = TermuxConstants.TERMUX_APP.RUN_COMMAND_SERVICE.ACTION_RUN_COMMAND;
private static final String TERMUX_HOME_PATH = "/data/data/com.termux/files/home";
/** /**
* 执行 Termux 命令(核心方法) * 执行 Termux 命令(核心方法)
@@ -114,7 +115,7 @@ public class TermuxCommandExecutor {
context, context,
"/data/data/com.termux/files/usr/bin/bash", // Termux 默认 bash 路径(正确) "/data/data/com.termux/files/usr/bin/bash", // Termux 默认 bash 路径(正确)
args, args,
"/data/data/com.termux/files/home", // 默认工作目录 TERMUX_HOME_PATH, // 默认工作目录
false, // 终端会话执行(可见) false, // 终端会话执行(可见)
null // 不输出到文件 null // 不输出到文件
); );
@@ -173,5 +174,49 @@ public class TermuxCommandExecutor {
LogUtils.d(TAG, "外部应用调用权限提示:" + tip); LogUtils.d(TAG, "外部应用调用权限提示:" + tip);
return tip; return tip;
} }
public static boolean openTermuxBash(Context context, String command) {
return openTermuxBash(context, command, "~");
}
public static boolean openTermuxBash(Context context, String command, String workDir) {
LogUtils.d(TAG, "openTermuxBash() 按钮点击执行Gradle命令实时输出");
// 1. 校验Termux是否安装
if (!TermuxCommandExecutor.isTermuxInstalled(context)) {
LogUtils.e(TAG, "openTermuxBash() 错误未安装Termux应用");
return false;
}
// 2. 定义核心路径确保路径与Termux中一致
String projectPath = TERMUX_HOME_PATH;
if (workDir.startsWith("~") || workDir.startsWith(".")) {
projectPath = TERMUX_HOME_PATH + "/" + workDir.substring(1);
}
// 3. 构造命令核心用stdbuf禁用缓冲实现实时输出
String targetCmd = "";
// 步骤1进入项目目录不存在则创建
targetCmd += "cd " + projectPath + " && ";
// 步骤2加载环境变量
targetCmd += "source ~/.bashrc && ";
// 步骤3显式配置PATH
targetCmd += "export PATH=/data/data/com.termux/files/usr/bin:$PATH && ";
// 步骤4用stdbuf禁用stdout/stderr缓冲关键执行Gradle命令
// -o0stdout无缓冲-e0stderr无缓冲-i0stdin无缓冲
//targetCmd += "stdbuf -o0 -e0 -i0 " + gradleFullPath + " task --all | grep assemble && ";
//targetCmd += "stdbuf -o0 -e0 -i0 " + gradleFullPath + " -Pandroid.aapt2FromMavenOverride=/data/data/com.termux/files/home/android-sdk/build-tools/34.0.4/aapt2 assembleBetaDebug && ";
targetCmd += "stdbuf -o0 -e0 -i0 bash && ";
// 步骤5执行成功提示
targetCmd += "echo '\n✅ 命令执行完成!' && echo '\n📌 当前目录:" + projectPath + "' && read -p '按回车键关闭终端...'";
// 4. 执行命令终端会话模式唤起Termux窗口
boolean cmdSuccess = TermuxCommandExecutor.executeTerminalCommand(context, targetCmd);
if (!cmdSuccess) {
return true;
}
return false;
}
} }

View File

@@ -0,0 +1,264 @@
package cc.winboll.studio.winboll.views;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Button;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.winboll.models.TermuxButtonModel;
/**
* 自定义Termux功能按钮控件
* 绑定TermuxButtonModel实体数据拦截点击事件做确认弹窗逻辑判断
* isCommitted为true直接执行点击事件为false弹出确认对话框二次确认
* @Author 豆包&ZhanGSKen<zhangsken@qq.com>
* @CreateTime 2026/04/30 10:57:00
* @EditTime 2026/04/30 13:52:15
*/
public class TermuxButton extends Button {
public static final String TAG = "TermuxButton";
/** 绑定按钮对应数据实体 */
private TermuxButtonModel buttonModel;
/** 保存外部设置的原始点击监听 */
private OnClickListener originClickListener;
//==================== 构造方法 ====================
/**
* 代码动态创建控件构造
* @param context 上下文
*/
public TermuxButton(Context context) {
super(context);
LogUtils.d(TAG, "TermuxButton 无参构造执行,上下文:" + context);
initView(null, null);
}
/**
* XML布局引用控件基础构造
* @param context 上下文
* @param attrs XML属性集
*/
public TermuxButton(Context context, AttributeSet attrs) {
super(context, attrs);
LogUtils.d(TAG, "TermuxButton XML构造执行");
initView(attrs, null);
}
/**
* XML布局带自定义属性构造
* @param context 上下文
* @param attrs XML属性集
* @param defStyleAttr 默认样式属性
*/
public TermuxButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
LogUtils.d(TAG, "TermuxButton 带样式属性构造执行");
initView(attrs, null);
}
/**
* 高版本Android完整全参构造
* @param context 上下文
* @param attrs XML属性集
* @param defStyleAttr 默认样式属性
* @param defStyleRes 默认样式资源
*/
public TermuxButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
LogUtils.d(TAG, "TermuxButton 全参构造执行");
initView(attrs, null);
}
/**
* 直接传入Model初始化控件构造
* @param context 上下文
* @param model 按钮数据实体
*/
public TermuxButton(Context context, TermuxButtonModel model) {
super(context);
LogUtils.d(TAG, "TermuxButton Model入参构造执行");
initView(null, model);
}
//==================== 核心初始化 ====================
/**
* 控件统一初始化方法
* @param attrs XML属性集合
* @param model 绑定数据实体
*/
private void initView(AttributeSet attrs, TermuxButtonModel model) {
this.buttonModel = model;
// 按钮基础默认配置
setClickable(true);
setFocusable(true);
// 解析XML布局自定义属性
if (attrs != null) {
parseXmlCustomAttr(attrs);
}
// 同步Model内按钮名称到控件展示文本
refreshButtonText();
// 绑定自定义拦截点击事件
setCustomClickEvent();
}
/**
* 解析XML布局属性读取原生android:text与自定义属性赋值到Model
* @param attrs XML属性集
*/
private void parseXmlCustomAttr(AttributeSet attrs) {
if (buttonModel == null) {
buttonModel = new TermuxButtonModel();
LogUtils.d(TAG, "自动初始化空的TermuxButtonModel实体");
}
// 读取原生android:text作为按钮名称
String androidText = attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "text");
// 读取自定义扩展属性
String exeCommand = attrs.getAttributeValue("http://schemas.android.com/apk/res-auto", "exeCommand");
String workDir = attrs.getAttributeValue("http://schemas.android.com/apk/res-auto", "workDir");
String isCommittedStr = attrs.getAttributeValue("http://schemas.android.com/apk/res-auto", "isCommitted");
String commitTitle = attrs.getAttributeValue("http://schemas.android.com/apk/res-auto", "commitTitle");
String commitInfo = attrs.getAttributeValue("http://schemas.android.com/apk/res-auto", "commitInfo");
// 属性赋值绑定
if (androidText != null) {
buttonModel.setButtonName(androidText);
}
if (exeCommand != null) {
buttonModel.setExeCommand(exeCommand);
}
if (workDir != null) {
buttonModel.setWorkDir(workDir);
}
if (isCommittedStr != null) {
buttonModel.setCommitted(Boolean.parseBoolean(isCommittedStr));
}
if (commitTitle != null) {
buttonModel.setCommitTitle(commitTitle);
}
if (commitInfo != null) {
buttonModel.setCommitInfo(commitInfo);
}
LogUtils.d(TAG, "XML属性解析完成按钮名称" + androidText);
}
/**
* 同步Model中buttonName更新按钮展示文字
*/
private void refreshButtonText() {
if (buttonModel != null) {
setText(buttonModel.getButtonName());
}
}
//==================== 点击事件相关 ====================
/**
* 重写点击监听设置,保存外部原始点击事件
* @param l 外部传入点击监听
*/
@Override
public void setOnClickListener(OnClickListener l) {
this.originClickListener = l;
LogUtils.d(TAG, "保存外部原始按钮点击监听");
}
/**
* 自定义拦截按钮点击逻辑
* isCommitted=true 直接执行原始点击事件
* isCommitted=false 弹出确认二次弹窗
*/
private void setCustomClickEvent() {
super.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (buttonModel == null) {
LogUtils.d(TAG, "无绑定Model直接执行原始点击事件");
if (originClickListener != null) {
originClickListener.onClick(view);
}
return;
}
boolean commitState = buttonModel.isCommitted();
LogUtils.d(TAG, "按钮点击触发isCommitted状态" + commitState);
if (commitState) {
// 无需确认,直接执行原有点击任务
if (originClickListener != null) {
originClickListener.onClick(view);
}
} else {
// 需要二次确认,弹出提示对话框
showCommitDialog();
}
}
});
}
/**
* 弹出操作确认对话框
* 标题commitTitle 内容commitInfo
* 取消:关闭弹窗无操作 确定:执行原始点击事件
*/
private void showCommitDialog() {
Context context = getContext();
String dialogTitle = buttonModel.getCommitTitle();
String dialogMsg = buttonModel.getCommitInfo();
// 空值默认兜底处理
if (dialogTitle == null || "".equals(dialogTitle)) {
dialogTitle = "温馨提示";
}
if (dialogMsg == null || "".equals(dialogMsg)) {
dialogMsg = "确定要执行该操作吗?";
}
LogUtils.d(TAG, "弹出确认对话框,标题:" + dialogTitle);
new AlertDialog.Builder(context)
.setTitle(dialogTitle)
.setMessage(dialogMsg)
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
LogUtils.d(TAG, "对话框点击取消,终止操作");
}
})
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
LogUtils.d(TAG, "对话框点击确定,继续执行操作");
if (originClickListener != null) {
originClickListener.onClick(TermuxButton.this);
}
}
})
.setCancelable(false)
.show();
}
//==================== Getter & Setter ====================
public TermuxButtonModel getButtonModel() {
return buttonModel;
}
/**
* 设置绑定按钮数据实体,自动刷新按钮展示文字
* @param buttonModel 数据实体类
*/
public void setButtonModel(TermuxButtonModel buttonModel) {
this.buttonModel = buttonModel;
LogUtils.d(TAG, "外部设置ButtonModel自动刷新按钮文本");
refreshButtonText();
}
}

View File

@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="top">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:title="@string/app_name"
app:subtitle="@string/my_termux_activity"
app:titleTextColor="@android:color/white"
app:subtitleTextColor="@android:color/white"/>
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.0">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1.0">
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<cc.winboll.studio.winboll.views.TermuxButton
android:id="@+id/btn_termux"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Termux"
android:textSize="18sp"
android:padding="16dp"
android:backgroundTint="@android:color/holo_blue_dark"
app:exeCommand="cd ~"
app:workDir="~"
app:isCommitted="true"
app:commitTitle="打开 Termux"
app:commitInfo="打开 Termux 应用"/>
<cc.winboll.studio.winboll.views.TermuxButton
android:id="@+id/btn_termuxworkspaces"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TermuxWorkSpaces"
android:textSize="18sp"
android:padding="16dp"
android:backgroundTint="@android:color/holo_blue_dark"
app:exeCommand="cd ~/TermuxWorkSpaces"
app:workDir="~"
app:isCommitted="false"
app:commitTitle="打开 TermuxWorkSpaces"
app:commitInfo="打开 Termux 应用,进入 TermuxWorkSpaces 目录。"/>
</LinearLayout>
</HorizontalScrollView>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="+"
android:id="@+id/btn_addtermuxbutton"/>
</LinearLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>

View File

@@ -5,6 +5,9 @@
android:id="@+id/item_home" android:id="@+id/item_home"
android:title="HOME"/> android:title="HOME"/>
<item <item
android:id="@+id/item_mytermux"
android:title="MyTermuxActivity"/>
<item
android:id="@+id/item_settings" android:id="@+id/item_settings"
android:title="Settings"/> android:title="Settings"/>
<item <item

View File

@@ -5,5 +5,13 @@
<attr name="toolbarTitleColor" format="color" /> <attr name="toolbarTitleColor" format="color" />
<attr name="toolbarBackgroundColor" format="color" /> <attr name="toolbarBackgroundColor" format="color" />
</declare-styleable> </declare-styleable>
<declare-styleable name="TermuxButton">
<attr name="exeCommand" format="string" />
<attr name="workDir" format="string" />
<attr name="isCommitted" format="boolean" />
<attr name="commitTitle" format="string" />
<attr name="commitInfo" format="string" />
</declare-styleable>
</resources> </resources>

View File

@@ -11,4 +11,5 @@
<string name="cn2_switch_disabled">金抖云 X</string> <string name="cn2_switch_disabled">金抖云 X</string>
<string name="tileservice_name">WinBoLL</string> <string name="tileservice_name">WinBoLL</string>
<string name="toolbar_icon_description">WinBoLL APP</string> <string name="toolbar_icon_description">WinBoLL APP</string>
<string name="my_termux_activity">MyTermuxActivity</string>
</resources> </resources>