diff --git a/mymessagemanager/build.properties b/mymessagemanager/build.properties index 9e280bd..f0febc4 100644 --- a/mymessagemanager/build.properties +++ b/mymessagemanager/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Wed Feb 11 05:29:19 HKT 2026 +#Fri May 08 11:33:06 GMT 2026 stageCount=8 libraryProject= baseVersion=15.12 publishVersion=15.12.7 -buildCount=0 +buildCount=9 baseBetaVersion=15.12.8 diff --git a/mymessagemanager/src/main/java/cc/winboll/studio/mymessagemanager/unittest/UnitTestActivity.java b/mymessagemanager/src/main/java/cc/winboll/studio/mymessagemanager/unittest/UnitTestActivity.java index d34fd81..d405dfb 100644 --- a/mymessagemanager/src/main/java/cc/winboll/studio/mymessagemanager/unittest/UnitTestActivity.java +++ b/mymessagemanager/src/main/java/cc/winboll/studio/mymessagemanager/unittest/UnitTestActivity.java @@ -11,20 +11,29 @@ import android.view.View; import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.libappbase.LogView; import cc.winboll.studio.mymessagemanager.R; +import cc.winboll.studio.mymessagemanager.views.ProtectModeTextView; public class UnitTestActivity extends Activity { public static final String TAG = "UnitTestActivity"; LogView mLogView; - + // 新增自定义控件 + ProtectModeTextView mProtectModeTv; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_unittest); - + mLogView = findViewById(R.id.logview); mLogView.start(); + + // 初始化ProtectModeTextView + mProtectModeTv = findViewById(R.id.protect_mode_tv); + // 设置测试文本,可自行修改 + String testText = "abcdefghijklmnopqrstuvwxyz消息管理 隐私保护 文本随机组合 滑动刻度测试1234567890"; + mProtectModeTv.setContentText(testText); } public void onMain(View view) { @@ -34,3 +43,4 @@ public class UnitTestActivity extends Activity { AddressUtils_Test.main(this); } } + diff --git a/mymessagemanager/src/main/java/cc/winboll/studio/mymessagemanager/views/ProtectModeTextView.java b/mymessagemanager/src/main/java/cc/winboll/studio/mymessagemanager/views/ProtectModeTextView.java new file mode 100644 index 0000000..003eb2a --- /dev/null +++ b/mymessagemanager/src/main/java/cc/winboll/studio/mymessagemanager/views/ProtectModeTextView.java @@ -0,0 +1,136 @@ +package cc.winboll.studio.mymessagemanager.views; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.widget.LinearLayout; +import android.widget.SeekBar; +import android.widget.TextView; +import cc.winboll.studio.mymessagemanager.R; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Random; + +/** + * 保护模式自定义控件 + * 最终规则: + * 1. 刻度范围 0~12 + * 2. 刻度值 = 每一组截取【相邻字符个数】 + * 3. 从头到尾按固定长度切块分组 + * 4. 所有分组收集后随机打乱再拼接输出 + * 5. 刻度0 = 不打乱,显示原文 + * 6. 按原生字符计算(包含空格、标点) + */ +public class ProtectModeTextView extends LinearLayout { + + private TextView tvContent; + private SeekBar seekBarScale; + private String originText; + private List charAllList; + private final Random random = new Random(); + + public ProtectModeTextView(Context context) { + super(context); + initView(context); + } + + public ProtectModeTextView(Context context, AttributeSet attrs) { + super(context, attrs); + initView(context); + } + + public ProtectModeTextView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initView(context); + } + + private void initView(Context context) { + LayoutInflater.from(context).inflate(R.layout.layout_protect_mode_textview, this, true); + tvContent = findViewById(R.id.tv_content); + seekBarScale = findViewById(R.id.seek_bar_scale); + + // 刻度 0 ~ 12 + seekBarScale.setMax(12); + seekBarScale.setProgress(0); + + charAllList = new ArrayList<>(); + + seekBarScale.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + handleTextLogic(progress); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) {} + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} + }); + } + + public void setContentText(String text) { + this.originText = text; + convertToCharList(text); + handleTextLogic(seekBarScale.getProgress()); + } + + private void convertToCharList(String text) { + charAllList.clear(); + if (text == null || text.isEmpty()) { + return; + } + char[] chars = text.toCharArray(); + for (char c : chars) { + charAllList.add(c); + } + } + + private void handleTextLogic(int groupSize) { + if (charAllList.isEmpty()) { + tvContent.setText(originText); + return; + } + + // 刻度0 原样不打乱 + if (groupSize <= 0) { + tvContent.setText(originText); + return; + } + + List groupList = new ArrayList<>(); + int totalLen = charAllList.size(); + + // 从头到尾 按 groupSize 个相邻字符切块 + int index = 0; + while (index < totalLen) { + StringBuilder sb = new StringBuilder(); + // 每一组取 groupSize 个相邻字符 + for (int i = 0; i < groupSize && index < totalLen; i++) { + sb.append(charAllList.get(index)); + index++; + } + groupList.add(sb.toString()); + } + + // 所有分组随机打乱 + Collections.shuffle(groupList, random); + + // 拼接输出 + StringBuilder result = new StringBuilder(); + for (String item : groupList) { + result.append(item); + } + + tvContent.setText(result.toString()); + } + + public String getOriginText() { + return originText; + } + + public void resetSeekBar() { + seekBarScale.setProgress(0); + } +} + diff --git a/mymessagemanager/src/main/res/layout/activity_unittest.xml b/mymessagemanager/src/main/res/layout/activity_unittest.xml index b37f8f1..6146c5f 100644 --- a/mymessagemanager/src/main/res/layout/activity_unittest.xml +++ b/mymessagemanager/src/main/res/layout/activity_unittest.xml @@ -1,44 +1,52 @@ + 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="match_parent"> - + - + - + + -