From be52292203aa38284386007e681e4926a5b48441 Mon Sep 17 00:00:00 2001 From: ZhanGSKen Date: Fri, 12 Dec 2025 13:22:34 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E6=95=B0=E6=8D=AE=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contacts/build.properties | 4 +- .../winboll/studio/contacts/MainActivity.java | 2 +- .../contacts/activities/AboutActivity.java | 97 +++-- .../contacts/activities/CallActivity.java | 194 ++++++---- .../contacts/activities/DialerActivity.java | 66 +++- .../contacts/activities/SettingsActivity.java | 8 +- .../contacts/activities/UnitTestActivity.java | 149 ++++--- .../contacts/activities/WinBollActivity.java | 38 +- .../contacts/adapters/CallLogAdapter.java | 185 +++++---- .../contacts/adapters/ContactAdapter.java | 162 ++++---- .../contacts/adapters/ImagePagerAdapter.java | 14 - .../adapters/PhoneConnectRuleAdapter.java | 362 +++++++++--------- .../cc/winboll/studio/contacts/dun/Rules.java | 4 +- .../contacts/fragments/CallLogFragment.java | 2 +- .../contacts/fragments/ContactsFragment.java | 2 +- .../{beans => model}/CallLogModel.java | 2 +- .../{beans => model}/ContactModel.java | 2 +- .../{beans => model}/MainServiceBean.java | 2 +- .../PhoneConnectRuleModel.java | 2 +- .../{beans => model}/RingTongBean.java | 2 +- .../{beans => model}/SettingsModel.java | 2 +- .../phonecallui/PhoneCallService.java | 2 +- .../contacts/services/AssistantService.java | 2 +- .../studio/contacts/services/MainService.java | 4 +- .../studio/contacts/views/DuInfoTextView.java | 2 +- 25 files changed, 761 insertions(+), 550 deletions(-) delete mode 100644 contacts/src/main/java/cc/winboll/studio/contacts/adapters/ImagePagerAdapter.java rename contacts/src/main/java/cc/winboll/studio/contacts/{beans => model}/CallLogModel.java (94%) rename contacts/src/main/java/cc/winboll/studio/contacts/{beans => model}/ContactModel.java (98%) rename contacts/src/main/java/cc/winboll/studio/contacts/{beans => model}/MainServiceBean.java (97%) rename contacts/src/main/java/cc/winboll/studio/contacts/{beans => model}/PhoneConnectRuleModel.java (98%) rename contacts/src/main/java/cc/winboll/studio/contacts/{beans => model}/RingTongBean.java (97%) rename contacts/src/main/java/cc/winboll/studio/contacts/{beans => model}/SettingsModel.java (99%) diff --git a/contacts/build.properties b/contacts/build.properties index 0f3a864..85fd1b0 100644 --- a/contacts/build.properties +++ b/contacts/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Fri Dec 12 04:27:50 GMT 2025 +#Fri Dec 12 05:20:34 GMT 2025 stageCount=1 libraryProject= baseVersion=15.12 publishVersion=15.12.0 -buildCount=2 +buildCount=5 baseBetaVersion=15.12.1 diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/MainActivity.java b/contacts/src/main/java/cc/winboll/studio/contacts/MainActivity.java index 488f942..20c16e4 100644 --- a/contacts/src/main/java/cc/winboll/studio/contacts/MainActivity.java +++ b/contacts/src/main/java/cc/winboll/studio/contacts/MainActivity.java @@ -28,7 +28,7 @@ import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentPagerAdapter; import androidx.viewpager.widget.ViewPager; import cc.winboll.studio.contacts.activities.SettingsActivity; -import cc.winboll.studio.contacts.beans.MainServiceBean; +import cc.winboll.studio.contacts.model.MainServiceBean; import cc.winboll.studio.contacts.fragments.CallLogFragment; import cc.winboll.studio.contacts.fragments.ContactsFragment; import cc.winboll.studio.contacts.fragments.LogFragment; diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/activities/AboutActivity.java b/contacts/src/main/java/cc/winboll/studio/contacts/activities/AboutActivity.java index 71d23e3..750f73d 100644 --- a/contacts/src/main/java/cc/winboll/studio/contacts/activities/AboutActivity.java +++ b/contacts/src/main/java/cc/winboll/studio/contacts/activities/AboutActivity.java @@ -1,31 +1,37 @@ package cc.winboll.studio.contacts.activities; -/** - * @Author ZhanGSKen - * @Date 2025/03/31 15:15:54 - * @Describe 应用介绍窗口 - */ import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.ViewGroup; import android.widget.LinearLayout; + import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; + import cc.winboll.studio.contacts.R; import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity; import cc.winboll.studio.libaes.models.APPInfo; -import cc.winboll.studio.libaes.views.AboutView; -import cc.winboll.studio.libappbase.GlobalApplication; import cc.winboll.studio.libaes.utils.WinBoLLActivityManager; +import cc.winboll.studio.libaes.views.AboutView; +import cc.winboll.studio.libappbase.LogUtils; +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/03/31 15:15:54 + * @Describe 应用介绍窗口 + */ public class AboutActivity extends AppCompatActivity implements IWinBoLLActivity { + // ====================== 常量定义区 ====================== public static final String TAG = "AboutActivity"; + private static final String BRANCH_NAME = "contacts"; - Context mContext; - Toolbar mToolbar; + // ====================== 成员变量区 ====================== + private Context mContext; + private Toolbar mToolbar; + // ====================== 接口实现区 ====================== @Override public Activity getActivity() { return this; @@ -36,58 +42,75 @@ public class AboutActivity extends AppCompatActivity implements IWinBoLLActivity return TAG; } + // ====================== 生命周期函数区 ====================== @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + LogUtils.d(TAG, "onCreate: 关于页面开始创建"); + mContext = this; setContentView(R.layout.activity_about); - mToolbar = findViewById(R.id.toolbar); - setSupportActionBar(mToolbar); - mToolbar.setSubtitle(TAG); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - - AboutView aboutView = CreateAboutView(); - // 在 Activity 的 onCreate 或其他生命周期方法中调用 -// LinearLayout layout = new LinearLayout(this); -// layout.setOrientation(LinearLayout.VERTICAL); -// // 创建布局参数(宽度和高度) -// ViewGroup.LayoutParams params = new ViewGroup.LayoutParams( -// ViewGroup.LayoutParams.MATCH_PARENT, -// ViewGroup.LayoutParams.MATCH_PARENT -// ); -// addContentView(aboutView, params); - - LinearLayout layout = findViewById(R.id.aboutviewroot_ll); - // 创建布局参数(宽度和高度) - ViewGroup.LayoutParams params = new ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT - ); - layout.addView(aboutView, params); - + // 初始化工具栏 + initToolbar(); + // 初始化关于页面视图 + initAboutView(); + // 注册Activity管理 WinBoLLActivityManager.getInstance().add(this); + + LogUtils.d(TAG, "onCreate: 关于页面初始化完成"); } @Override protected void onDestroy() { super.onDestroy(); + LogUtils.d(TAG, "onDestroy: 关于页面开始销毁"); WinBoLLActivityManager.getInstance().registeRemove(this); + LogUtils.d(TAG, "onDestroy: 关于页面销毁完成"); } - public AboutView CreateAboutView() { - String szBranchName = "contacts"; + // ====================== 控件初始化函数区 ====================== + private void initToolbar() { + LogUtils.d(TAG, "initToolbar: 初始化工具栏"); + // Java7 适配:添加强制类型转换 + mToolbar = (Toolbar) findViewById(R.id.toolbar); + setSupportActionBar(mToolbar); + mToolbar.setSubtitle(TAG); + // 非空判断,避免空指针异常 + if (getSupportActionBar() != null) { + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + } + + private void initAboutView() { + LogUtils.d(TAG, "initAboutView: 初始化关于页面内容视图"); + AboutView aboutView = createAboutView(); + LinearLayout layout = (LinearLayout) findViewById(R.id.aboutviewroot_ll); + + ViewGroup.LayoutParams params = new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ); + layout.addView(aboutView, params); + LogUtils.d(TAG, "initAboutView: AboutView已添加到布局"); + } + + // ====================== 业务逻辑函数区 ====================== + private AboutView createAboutView() { + LogUtils.d(TAG, "createAboutView: 构建APP信息并创建AboutView"); APPInfo appInfo = new APPInfo(); appInfo.setAppName("Contacts"); appInfo.setAppIcon(cc.winboll.studio.libaes.R.drawable.ic_winboll); appInfo.setAppDescription("这是可以根据正则表达式匹配拦截骚扰电话的手机拨号应用。"); appInfo.setAppGitName("WinBoLL"); appInfo.setAppGitOwner("Studio"); - appInfo.setAppGitAPPBranch(szBranchName); - appInfo.setAppGitAPPSubProjectFolder(szBranchName); + appInfo.setAppGitAPPBranch(BRANCH_NAME); + appInfo.setAppGitAPPSubProjectFolder(BRANCH_NAME); appInfo.setAppHomePage("https://www.winboll.cc/apks/index.php?project=Contacts"); appInfo.setAppAPKName("Contacts"); appInfo.setAppAPKFolderName("Contacts"); + return new AboutView(mContext, appInfo); } } + diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/activities/CallActivity.java b/contacts/src/main/java/cc/winboll/studio/contacts/activities/CallActivity.java index 32e48d1..b06356d 100644 --- a/contacts/src/main/java/cc/winboll/studio/contacts/activities/CallActivity.java +++ b/contacts/src/main/java/cc/winboll/studio/contacts/activities/CallActivity.java @@ -1,10 +1,5 @@ package cc.winboll.studio.contacts.activities; -/** - * @Author ZhanGSKen - * @Date 2025/02/20 17:15:46 - * @Describe 拨号窗口 - */ import android.Manifest; import android.content.Intent; import android.content.pm.PackageManager; @@ -20,99 +15,144 @@ import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; -import cc.winboll.studio.contacts.MainActivity; import cc.winboll.studio.contacts.R; +import cc.winboll.studio.libappbase.LogUtils; +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/02/20 17:15:46 + * @Describe 拨号窗口 + */ public class CallActivity extends AppCompatActivity { - public static final String TAG = "CallActivity"; + // ====================== 常量定义区 ====================== + public static final String TAG = "CallActivity"; private static final int REQUEST_CALL_PHONE = 1; + + // ====================== UI控件区 ====================== private EditText phoneNumberEditText; private TextView callStatusTextView; + private Button dialButton; + + // ====================== 业务成员区 ====================== private TelephonyManager telephonyManager; private MyPhoneStateListener phoneStateListener; + // ====================== 生命周期函数区 ====================== @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - //setContentView(R.layout.activity_main); + LogUtils.d(TAG, "onCreate: 拨号页面开始创建"); setContentView(R.layout.activity_call); - phoneNumberEditText = findViewById(R.id.phone_number); - Button dialButton = findViewById(R.id.dial_button); - callStatusTextView = findViewById(R.id.call_status); - - dialButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - String phoneNumber = phoneNumberEditText.getText().toString().trim(); - if (!phoneNumber.isEmpty()) { - if (ContextCompat.checkSelfPermission(CallActivity.this, Manifest.permission.CALL_PHONE) - != PackageManager.PERMISSION_GRANTED) { - ActivityCompat.requestPermissions(CallActivity.this, - new String[]{Manifest.permission.CALL_PHONE}, - REQUEST_CALL_PHONE); - } else { - dialPhoneNumber(phoneNumber); - } - } else { - Toast.makeText(CallActivity.this, "请输入电话号码", Toast.LENGTH_SHORT).show(); - } - } - }); - - // 初始化TelephonyManager和PhoneStateListener - telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); - phoneStateListener = new MyPhoneStateListener(); - telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); - } - - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - if (requestCode == REQUEST_CALL_PHONE) { - if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - String phoneNumber = phoneNumberEditText.getText().toString().trim(); - dialPhoneNumber(phoneNumber); - } else { - Toast.makeText(this, "未授予拨打电话权限", Toast.LENGTH_SHORT).show(); - } - } - } - - private void dialPhoneNumber(String phoneNumber) { - Intent intent = new Intent(Intent.ACTION_CALL); - intent.setData(android.net.Uri.parse("tel:" + phoneNumber)); - if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) { - return; - } - startActivity(intent); - } - - private class MyPhoneStateListener extends PhoneStateListener { - @Override - public void onCallStateChanged(int state, String incomingNumber) { - switch (state) { - case TelephonyManager.CALL_STATE_IDLE: - callStatusTextView.setText("电话已挂断"); - break; - case TelephonyManager.CALL_STATE_OFFHOOK: - callStatusTextView.setText("正在通话中"); - break; - case TelephonyManager.CALL_STATE_RINGING: - callStatusTextView.setText("来电: " + incomingNumber); - break; - } - } + // 初始化控件 + initViews(); + // 初始化电话状态监听 + initPhoneStateListener(); + LogUtils.d(TAG, "onCreate: 拨号页面初始化完成"); } @Override protected void onDestroy() { super.onDestroy(); - // 取消监听 - if (telephonyManager != null) { + LogUtils.d(TAG, "onDestroy: 拨号页面开始销毁"); + // 取消电话状态监听,避免内存泄漏 + if (telephonyManager != null && phoneStateListener != null) { telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE); + LogUtils.d(TAG, "onDestroy: 电话状态监听已取消"); + } + LogUtils.d(TAG, "onDestroy: 拨号页面销毁完成"); + } + + // ====================== 权限回调函数区 ====================== + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + LogUtils.d(TAG, "onRequestPermissionsResult: 权限请求回调,requestCode=" + requestCode); + if (requestCode == REQUEST_CALL_PHONE) { + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + LogUtils.d(TAG, "onRequestPermissionsResult: 拨打电话权限授予成功"); + String phoneNumber = phoneNumberEditText.getText().toString().trim(); + dialPhoneNumber(phoneNumber); + } else { + LogUtils.w(TAG, "onRequestPermissionsResult: 拨打电话权限被拒绝"); + Toast.makeText(this, "未授予拨打电话权限", Toast.LENGTH_SHORT).show(); + } + } + } + + // ====================== 控件初始化函数区 ====================== + private void initViews() { + LogUtils.d(TAG, "initViews: 初始化UI控件"); + // Java7 适配:添加强制类型转换 + phoneNumberEditText = (EditText) findViewById(R.id.phone_number); + dialButton = (Button) findViewById(R.id.dial_button); + callStatusTextView = (TextView) findViewById(R.id.call_status); + + // 设置拨号按钮点击事件 + dialButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + String phoneNumber = phoneNumberEditText.getText().toString().trim(); + LogUtils.d(TAG, "initViews: 拨号按钮点击,号码=" + phoneNumber); + if (phoneNumber.isEmpty()) { + Toast.makeText(CallActivity.this, "请输入电话号码", Toast.LENGTH_SHORT).show(); + return; + } + + // 权限检查 + if (ContextCompat.checkSelfPermission(CallActivity.this, Manifest.permission.CALL_PHONE) + != PackageManager.PERMISSION_GRANTED) { + LogUtils.w(TAG, "initViews: 拨打电话权限未授予,发起权限申请"); + ActivityCompat.requestPermissions(CallActivity.this, + new String[]{Manifest.permission.CALL_PHONE}, + REQUEST_CALL_PHONE); + } else { + dialPhoneNumber(phoneNumber); + } + } + }); + } + + // ====================== 电话状态监听初始化函数区 ====================== + private void initPhoneStateListener() { + LogUtils.d(TAG, "initPhoneStateListener: 初始化电话状态监听"); + telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); + phoneStateListener = new MyPhoneStateListener(); + telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); + } + + // ====================== 核心业务函数区 ====================== + private void dialPhoneNumber(String phoneNumber) { + LogUtils.d(TAG, "dialPhoneNumber: 发起拨号,号码=" + phoneNumber); + Intent intent = new Intent(Intent.ACTION_CALL); + intent.setData(android.net.Uri.parse("tel:" + phoneNumber)); + if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) { + LogUtils.e(TAG, "dialPhoneNumber: 拨打电话权限缺失,拨号失败"); + return; + } + startActivity(intent); + } + + // ====================== 内部电话状态监听类 ====================== + private class MyPhoneStateListener extends PhoneStateListener { + @Override + public void onCallStateChanged(int state, String incomingNumber) { + super.onCallStateChanged(state, incomingNumber); + switch (state) { + case TelephonyManager.CALL_STATE_IDLE: + callStatusTextView.setText("电话已挂断"); + LogUtils.d(TAG, "MyPhoneStateListener: 通话状态-挂断"); + break; + case TelephonyManager.CALL_STATE_OFFHOOK: + callStatusTextView.setText("正在通话中"); + LogUtils.d(TAG, "MyPhoneStateListener: 通话状态-通话中"); + break; + case TelephonyManager.CALL_STATE_RINGING: + callStatusTextView.setText("来电: " + incomingNumber); + LogUtils.d(TAG, "MyPhoneStateListener: 通话状态-来电,号码=" + incomingNumber); + break; + } } } } diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/activities/DialerActivity.java b/contacts/src/main/java/cc/winboll/studio/contacts/activities/DialerActivity.java index abcb72a..0fc4134 100644 --- a/contacts/src/main/java/cc/winboll/studio/contacts/activities/DialerActivity.java +++ b/contacts/src/main/java/cc/winboll/studio/contacts/activities/DialerActivity.java @@ -1,40 +1,80 @@ package cc.winboll.studio.contacts.activities; -/** - * @Author ZhanGSKen - * @Date 2025/02/20 20:18:26 - */ import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; +import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import cc.winboll.studio.contacts.R; +import cc.winboll.studio.libappbase.LogUtils; +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/02/20 20:18:26 + * @Describe 拨号盘窗口(跳转到系统拨号界面) + */ public class DialerActivity extends AppCompatActivity { + // ====================== 常量定义区 ====================== public static final String TAG = "DialerActivity"; + // ====================== UI控件区 ====================== private EditText phoneNumberEditText; + private Button dialButton; + // ====================== 生命周期函数区 ====================== @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + LogUtils.d(TAG, "onCreate: 拨号盘页面开始创建"); setContentView(R.layout.activity_dialer); - phoneNumberEditText = findViewById(R.id.phone_number_edit_text); - Button dialButton = findViewById(R.id.dial_button); + // 初始化UI控件与点击事件 + initViews(); + LogUtils.d(TAG, "onCreate: 拨号盘页面初始化完成"); + } + @Override + protected void onDestroy() { + super.onDestroy(); + LogUtils.d(TAG, "onDestroy: 拨号盘页面已销毁"); + } + + // ====================== 控件初始化函数区 ====================== + private void initViews() { + LogUtils.d(TAG, "initViews: 初始化UI控件"); + // Java7 适配:添加强制类型转换 + phoneNumberEditText = (EditText) findViewById(R.id.phone_number_edit_text); + dialButton = (Button) findViewById(R.id.dial_button); + + // 设置拨号按钮点击事件 dialButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - String phoneNumber = phoneNumberEditText.getText().toString(); - Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phoneNumber)); - startActivity(intent); - } - }); + @Override + public void onClick(View v) { + String phoneNumber = phoneNumberEditText.getText().toString().trim(); + LogUtils.d(TAG, "initViews: 拨号按钮点击,输入号码=" + phoneNumber); + + // 空号码校验 + if (phoneNumber.isEmpty()) { + LogUtils.w(TAG, "initViews: 拨号失败,号码为空"); + Toast.makeText(DialerActivity.this, "请输入有效电话号码", Toast.LENGTH_SHORT).show(); + return; + } + + // 跳转到系统拨号界面 + Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phoneNumber)); + if (intent.resolveActivity(getPackageManager()) != null) { + startActivity(intent); + LogUtils.d(TAG, "initViews: 成功跳转到系统拨号界面"); + } else { + LogUtils.e(TAG, "initViews: 跳转失败,无可用拨号应用"); + Toast.makeText(DialerActivity.this, "未找到可用拨号应用", Toast.LENGTH_SHORT).show(); + } + } + }); } } diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/activities/SettingsActivity.java b/contacts/src/main/java/cc/winboll/studio/contacts/activities/SettingsActivity.java index 5b1e3e4..1619747 100644 --- a/contacts/src/main/java/cc/winboll/studio/contacts/activities/SettingsActivity.java +++ b/contacts/src/main/java/cc/winboll/studio/contacts/activities/SettingsActivity.java @@ -22,10 +22,10 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import cc.winboll.studio.contacts.R; import cc.winboll.studio.contacts.adapters.PhoneConnectRuleAdapter; -import cc.winboll.studio.contacts.beans.MainServiceBean; -import cc.winboll.studio.contacts.beans.PhoneConnectRuleModel; -import cc.winboll.studio.contacts.beans.RingTongBean; -import cc.winboll.studio.contacts.beans.SettingsModel; +import cc.winboll.studio.contacts.model.MainServiceBean; +import cc.winboll.studio.contacts.model.PhoneConnectRuleModel; +import cc.winboll.studio.contacts.model.RingTongBean; +import cc.winboll.studio.contacts.model.SettingsModel; import cc.winboll.studio.contacts.bobulltoon.TomCat; import cc.winboll.studio.contacts.dun.Rules; import cc.winboll.studio.contacts.services.MainService; diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/activities/UnitTestActivity.java b/contacts/src/main/java/cc/winboll/studio/contacts/activities/UnitTestActivity.java index c63ba08..f0c7a9d 100644 --- a/contacts/src/main/java/cc/winboll/studio/contacts/activities/UnitTestActivity.java +++ b/contacts/src/main/java/cc/winboll/studio/contacts/activities/UnitTestActivity.java @@ -11,84 +11,123 @@ import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.libappbase.LogView; /** - * @Author ZhanGSKen + * @Author ZhanGSKen&豆包大模型 * @Date 2025/03/02 16:07:04 + * @Describe 规则单元测试页面 */ public class UnitTestActivity extends Activity { + // ====================== 常量定义区 ====================== public static final String TAG = "UnitTestActivity"; - LogView logView; + // ====================== UI控件区 ====================== + private LogView logView; + private EditText etPhone; + // ====================== 生命周期函数区 ====================== @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + LogUtils.d(TAG, "onCreate: 单元测试页面开始创建"); setContentView(R.layout.activity_unittest); - logView = findViewById(R.id.logview); + + // 初始化控件 + initViews(); + LogUtils.d(TAG, "onCreate: 单元测试页面初始化完成"); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + LogUtils.d(TAG, "onDestroy: 单元测试页面开始销毁"); + if (logView != null) { + // 若LogView有停止方法,建议调用避免资源泄漏 + // logView.stop(); + LogUtils.d(TAG, "onDestroy: LogView资源已处理"); + } + LogUtils.d(TAG, "onDestroy: 单元测试页面销毁完成"); + } + + // ====================== 控件初始化函数区 ====================== + private void initViews() { + LogUtils.d(TAG, "initViews: 初始化UI控件"); + // Java7 适配:添加强制类型转换 + logView = (LogView) findViewById(R.id.logview); + etPhone = (EditText) findViewById(R.id.phone_et); + + // 启动日志视图 logView.start(); + LogUtils.d(TAG, "initViews: LogView已启动"); } + // ====================== 点击事件测试函数区 ====================== + /** + * 测试单个号码匹配规则 + */ public void onTestPhone(View view) { - // 开始测试数据 - EditText etPhone = findViewById(R.id.phone_et); - Rules rules = Rules.getInstance(this); + LogUtils.d(TAG, "onTestPhone: 开始测试单个号码规则匹配"); String phone = etPhone.getText().toString().trim(); - LogUtils.d(TAG, String.format("Test phone : %s\n%s", phone, rules.isAllowed(phone))); - - } - - public void onTestMain(View view) { - LogUtils.d(TAG, "IntUtils.unittest_getIntInRange();"); - IntUtils.unittest_getIntInRange(); - - Rules rules = Rules.getInstance(this); - - // 如果没有规则就添加测试规则 - if (rules.getPhoneBlacRuleBeanList().size() == 0) { - // 手机号码允许 - // 中国手机号码正则表达式,以1开头,第二位可以是3、4、5、6、7、8、9,后面跟9位数字 - String regex = "^1[3-9]\\d{9}$"; - rules.add(regex, true, true); - - // 指定区号号码允许 - regex = "^0660\\d+$"; - rules.add(regex, true, true); - - // 指定区号号码允许 - regex = "^020\\d+$"; - rules.add(regex, true, true); - - // 添加默认拒接规则 - regex = ".*"; - rules.add(regex, false, true); - - // 保存规则到文件 - rules.saveRules(); + if (phone.isEmpty()) { + LogUtils.w(TAG, "onTestPhone: 测试号码为空,跳过匹配"); + return; } - // 开始测试数据 - String phone = "16769764848"; - LogUtils.d(TAG, String.format("Test phone : %s\n%s", phone, rules.isAllowed(phone))); + Rules rules = Rules.getInstance(this); + boolean isAllowed = rules.isAllowed(phone); + LogUtils.d(TAG, String.format("onTestPhone: 测试号码: %s | 匹配结果: %s", phone, isAllowed)); + } - phone = "16856582777"; - LogUtils.d(TAG, String.format("Test phone : %s\n%s", phone, rules.isAllowed(phone))); + /** + * 批量测试预设号码规则匹配 + */ + public void onTestMain(View view) { + LogUtils.d(TAG, "onTestMain: 开始批量测试号码规则匹配"); + // 测试IntUtils工具类方法 + LogUtils.d(TAG, "onTestMain: 执行 IntUtils.unittest_getIntInRange() 测试"); + IntUtils.unittest_getIntInRange(); - phone = "17519703124"; - LogUtils.d(TAG, String.format("Test phone : %s\n%s", phone, rules.isAllowed(phone))); + // 初始化规则实例 + Rules rules = Rules.getInstance(this); + // 无规则时添加测试规则集 + initTestRulesIfEmpty(rules); - phone = "0205658955"; - LogUtils.d(TAG, String.format("Test phone : %s\n%s", phone, rules.isAllowed(phone))); + // 预设测试号码列表 + String[] testPhones = { + "16769764848", "16856582777", "17519703124", + "0205658955", "0108965253", "+8616769764848", + "4005816769764848", "95566" + }; - phone = "0108965253"; - LogUtils.d(TAG, String.format("Test phone : %s\n%s", phone, rules.isAllowed(phone))); + // 遍历测试号码并输出结果 + for (String phone : testPhones) { + boolean isAllowed = rules.isAllowed(phone); + LogUtils.d(TAG, String.format("onTestMain: 测试号码: %s | 匹配结果: %s", phone, isAllowed)); + } + LogUtils.d(TAG, "onTestMain: 批量号码规则测试完成"); + } - phone = "+8616769764848"; - LogUtils.d(TAG, String.format("Test phone : %s\n%s", phone, rules.isAllowed(phone))); + // ====================== 私有工具函数区 ====================== + /** + * 规则集为空时初始化测试规则 + */ + private void initTestRulesIfEmpty(Rules rules) { + if (rules.getPhoneBlacRuleBeanList().size() == 0) { + LogUtils.d(TAG, "initTestRulesIfEmpty: 当前无规则,添加测试规则集"); + // 规则1:中国手机号允许 + rules.add("^1[3-9]\\d{9}$", true, true); + // 规则2:0660区号号码允许 + rules.add("^0660\\d+$", true, true); + // 规则3:020区号号码允许 + rules.add("^020\\d+$", true, true); + // 规则4:默认拒接所有号码 + rules.add(".*", false, true); - phone = "4005816769764848"; - LogUtils.d(TAG, String.format("Test phone : %s\n%s", phone, rules.isAllowed(phone))); - - phone = "95566"; - LogUtils.d(TAG, String.format("Test phone : %s\n%s", phone, rules.isAllowed(phone))); + // 保存规则到本地 + rules.saveRules(); + LogUtils.d(TAG, "initTestRulesIfEmpty: 测试规则集已保存"); + } else { + LogUtils.d(TAG, "initTestRulesIfEmpty: 当前已有规则,跳过初始化"); + } } } + diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/activities/WinBollActivity.java b/contacts/src/main/java/cc/winboll/studio/contacts/activities/WinBollActivity.java index 6e1530d..9cabbaf 100644 --- a/contacts/src/main/java/cc/winboll/studio/contacts/activities/WinBollActivity.java +++ b/contacts/src/main/java/cc/winboll/studio/contacts/activities/WinBollActivity.java @@ -1,10 +1,5 @@ package cc.winboll.studio.contacts.activities; -/** - * @Author ZhanGSKen - * @Date 2025/03/31 15:16:45 - * @Describe 应用窗口基类 - */ import android.app.Activity; import android.os.Bundle; import android.view.MenuItem; @@ -12,13 +7,22 @@ import androidx.appcompat.app.AppCompatActivity; import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity; import cc.winboll.studio.libaes.models.AESThemeBean; import cc.winboll.studio.libaes.utils.AESThemeUtil; +import cc.winboll.studio.libappbase.LogUtils; +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/03/31 15:16:45 + * @Describe 应用窗口基类,统一处理主题设置与导航返回 + */ public class WinBollActivity extends AppCompatActivity implements IWinBoLLActivity { + // ====================== 常量定义区 ====================== public static final String TAG = "WinBollActivity"; + // ====================== 成员变量区 ====================== protected volatile AESThemeBean.ThemeType mThemeType; + // ====================== 接口实现区 ====================== @Override public Activity getActivity() { return this; @@ -29,14 +33,24 @@ public class WinBollActivity extends AppCompatActivity implements IWinBoLLActivi return TAG; } + // ====================== 生命周期函数区 ====================== @Override protected void onCreate(Bundle savedInstanceState) { + LogUtils.d(TAG, "onCreate: 基类页面开始创建"); + // 优先设置主题,再执行父类初始化 mThemeType = getThemeType(); setThemeStyle(); super.onCreate(savedInstanceState); + LogUtils.d(TAG, "onCreate: 基类主题设置完成,当前主题类型=" + mThemeType); } + // ====================== 主题相关函数区 ====================== + /** + * 获取当前应用主题类型 + */ AESThemeBean.ThemeType getThemeType() { + LogUtils.d(TAG, "getThemeType: 获取应用主题类型"); + // 注释的SharedPreferences逻辑保留,便于后续扩展 /*SharedPreferences sharedPreferences = getSharedPreferences( SHAREDPREFERENCES_NAME, MODE_PRIVATE); return AESThemeBean.ThemeType.values()[((sharedPreferences.getInt(DRAWER_THEME_TYPE, AESThemeBean.ThemeType.DEFAULT.ordinal())))]; @@ -44,17 +58,27 @@ public class WinBollActivity extends AppCompatActivity implements IWinBoLLActivi return AESThemeBean.getThemeStyleType(AESThemeUtil.getThemeTypeID(getApplicationContext())); } + /** + * 应用当前主题样式 + */ void setThemeStyle() { - //setTheme(AESThemeBean.getThemeStyle(getThemeType())); + LogUtils.d(TAG, "setThemeStyle: 开始设置应用主题"); + // 替换原注释逻辑,使用AESThemeUtil获取的主题ID setTheme(AESThemeUtil.getThemeTypeID(getApplicationContext())); + LogUtils.d(TAG, "setThemeStyle: 主题设置完成"); } + // ====================== 菜单与导航函数区 ====================== @Override public boolean onOptionsItemSelected(MenuItem item) { - if(item.getItemId() == android.R.id.home) { + LogUtils.d(TAG, "onOptionsItemSelected: 菜单选项点击,itemId=" + item.getItemId()); + // 处理导航栏返回按钮点击事件 + if (item.getItemId() == android.R.id.home) { + LogUtils.d(TAG, "onOptionsItemSelected: 点击导航返回按钮,关闭当前页面"); finish(); return true; } return super.onOptionsItemSelected(item); } } + diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/adapters/CallLogAdapter.java b/contacts/src/main/java/cc/winboll/studio/contacts/adapters/CallLogAdapter.java index 05be154..7d0e757 100644 --- a/contacts/src/main/java/cc/winboll/studio/contacts/adapters/CallLogAdapter.java +++ b/contacts/src/main/java/cc/winboll/studio/contacts/adapters/CallLogAdapter.java @@ -1,10 +1,5 @@ package cc.winboll.studio.contacts.adapters; -/** - * @Author ZhanGSKen - * @Date 2025/02/26 13:09:32 - * @Describe CallLogAdapter - */ import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; @@ -13,125 +8,167 @@ import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.widget.Button; import android.widget.PopupMenu; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import cc.winboll.studio.contacts.R; -import cc.winboll.studio.contacts.beans.CallLogModel; +import cc.winboll.studio.contacts.model.CallLogModel; import cc.winboll.studio.contacts.utils.ContactUtils; import cc.winboll.studio.libaes.views.AOHPCTCSeekBar; +import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.libappbase.ToastUtils; import java.text.SimpleDateFormat; import java.util.List; import java.util.Locale; +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/02/26 13:09:32 + * @Describe 通话记录列表适配器 + */ public class CallLogAdapter extends RecyclerView.Adapter { + + // ====================== 常量定义区 ====================== public static final String TAG = "CallLogAdapter"; + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()); + // ====================== 成员变量区 ====================== + private Context mContext; private List callLogList; - ContactUtils mContactUtils; - Context mContext; + private ContactUtils mContactUtils; + // ====================== 构造函数区 ====================== public CallLogAdapter(Context context, List callLogList) { - mContext = context; - this.mContactUtils = ContactUtils.getInstance(mContext); + LogUtils.d(TAG, "CallLogAdapter: 初始化适配器,数据量=" + callLogList.size()); + this.mContext = context; this.callLogList = callLogList; + this.mContactUtils = ContactUtils.getInstance(mContext); } - - public void relaodContacts() { - this.mContactUtils.relaodContacts(); - } + // ====================== 公共方法区 ====================== + /** + * 重新加载联系人数据 + */ + public void relaodContacts() { + LogUtils.d(TAG, "relaodContacts: 开始重新加载联系人数据"); + this.mContactUtils.relaodContacts(); + notifyDataSetChanged(); + LogUtils.d(TAG, "relaodContacts: 联系人数据加载完成,列表已刷新"); + } + + // ====================== RecyclerView 重写方法区 ====================== @NonNull @Override public CallLogViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + LogUtils.d(TAG, "onCreateViewHolder: 创建列表项ViewHolder"); View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_call_log, parent, false); return new CallLogViewHolder(view); } @Override public void onBindViewHolder(@NonNull CallLogViewHolder holder, int position) { + LogUtils.d(TAG, "onBindViewHolder: 绑定列表项数据,position=" + position); final CallLogModel callLog = callLogList.get(position); - holder.phoneNumber.setText(callLog.getPhoneNumber() + "☎" + mContactUtils.getContactsName(callLog.getPhoneNumber())); - holder.phoneNumber.setOnLongClickListener(new View.OnLongClickListener() { + + // 绑定通话号码与联系人名称 + String contactName = mContactUtils.getContactsName(callLog.getPhoneNumber()); + String phoneText = callLog.getPhoneNumber() + "☎" + (contactName == null ? "" : contactName); + holder.phoneNumber.setText(phoneText); + + // 号码长按弹出菜单事件 + holder.phoneNumber.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View p1) { - // 弹出复制菜单 - PopupMenu menu = new PopupMenu(mContext, holder.phoneNumber); - //加载菜单资源 - menu.getMenuInflater().inflate(R.menu.toolbar_calllog_phonenumber, menu.getMenu()); - //设置点击事件的响应 - menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem menuItem) { - int nItemId = menuItem.getItemId(); - if (nItemId == R.id.item_calllog_phonenumber_copy) { - // Gets a handle to the clipboard service. - ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE); - // Creates a new text clip to put on the clipboard - ClipData clip = ClipData.newPlainText("simple text", callLog.getPhoneNumber()); - // Set the clipboard's primary clip. - clipboard.setPrimaryClip(clip); - Toast.makeText(mContext, "Copy to clipboard.", Toast.LENGTH_SHORT).show(); - } else if (nItemId == R.id.item_calllog_phonenumber_add_contact) { - //ToastUtils.show(callLog.getPhoneNumber()); - ContactUtils.jumpToAddContact(mContext, callLog.getPhoneNumber()); - } - - return true; - } - }); - //一定要调用show()来显示弹出式菜单 - menu.show(); - + showPhonePopupMenu(holder.phoneNumber, callLog); return true; } }); - - holder.callStatus.setText(callLog.getCallStatus()); - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()); - holder.callDate.setText(dateFormat.format(callLog.getCallDate())); - // 初始化拉动后拨号控件 - holder.dialAOHPCTCSeekBar.setThumb(holder.itemView.getContext().getDrawable(R.drawable.ic_call)); - holder.dialAOHPCTCSeekBar.setBlurRightDP(80); - holder.dialAOHPCTCSeekBar.setThumbOffset(0); - holder.dialAOHPCTCSeekBar.setOnOHPCListener( - new AOHPCTCSeekBar.OnOHPCListener(){ - @Override - public void onOHPCommit() { - String phoneNumber = callLog.getPhoneNumber().replaceAll("\\s", ""); - ToastUtils.show(phoneNumber); - Intent intent = new Intent(Intent.ACTION_CALL); - intent.setData(android.net.Uri.parse("tel:" + phoneNumber)); - // 添加 FLAG_ACTIVITY_NEW_TASK 标志 - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - holder.itemView.getContext().startActivity(intent); - } - }); + // 绑定通话状态与时间 + holder.callStatus.setText(callLog.getCallStatus()); + holder.callDate.setText(DATE_FORMAT.format(callLog.getCallDate())); + + // 初始化滑动拨号SeekBar + initDialSeekBar(holder.dialAOHPCTCSeekBar, callLog); } @Override public int getItemCount() { - return callLogList.size(); + return callLogList == null ? 0 : callLogList.size(); } + // ====================== 私有工具方法区 ====================== + /** + * 显示号码操作弹窗菜单 + */ + private void showPhonePopupMenu(View anchorView, final CallLogModel callLog) { + LogUtils.d(TAG, "showPhonePopupMenu: 弹出号码操作菜单"); + PopupMenu menu = new PopupMenu(mContext, anchorView); + menu.getMenuInflater().inflate(R.menu.toolbar_calllog_phonenumber, menu.getMenu()); + + menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem menuItem) { + int itemId = menuItem.getItemId(); + if (itemId == R.id.item_calllog_phonenumber_copy) { + // 复制号码到剪贴板 + ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clip = ClipData.newPlainText("call_log_phone", callLog.getPhoneNumber()); + clipboard.setPrimaryClip(clip); + Toast.makeText(mContext, "Copy to clipboard.", Toast.LENGTH_SHORT).show(); + LogUtils.d(TAG, "showPhonePopupMenu: 号码" + callLog.getPhoneNumber() + "已复制到剪贴板"); + } else if (itemId == R.id.item_calllog_phonenumber_add_contact) { + // 跳转到添加联系人页面 + ContactUtils.jumpToAddContact(mContext, callLog.getPhoneNumber()); + LogUtils.d(TAG, "showPhonePopupMenu: 跳转添加联系人页面,号码=" + callLog.getPhoneNumber()); + } + return true; + } + }); + menu.show(); + } + + /** + * 初始化滑动拨号SeekBar + */ + private void initDialSeekBar(AOHPCTCSeekBar seekBar, final CallLogModel callLog) { + LogUtils.d(TAG, "initDialSeekBar: 初始化滑动拨号控件"); + seekBar.setThumb(seekBar.getContext().getDrawable(R.drawable.ic_call)); + seekBar.setBlurRightDP(80); + seekBar.setThumbOffset(0); + + seekBar.setOnOHPCListener(new AOHPCTCSeekBar.OnOHPCListener() { + @Override + public void onOHPCommit() { + String phoneNumber = callLog.getPhoneNumber().replaceAll("\\s", ""); + LogUtils.d(TAG, "initDialSeekBar: 滑动拨号触发,号码=" + phoneNumber); + ToastUtils.show(phoneNumber); + + Intent intent = new Intent(Intent.ACTION_CALL); + intent.setData(android.net.Uri.parse("tel:" + phoneNumber)); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(intent); + } + }); + } + + // ====================== ViewHolder 内部类 ====================== public class CallLogViewHolder extends RecyclerView.ViewHolder { - TextView phoneNumber, callStatus, callDate; - Button dialButton; + TextView phoneNumber; + TextView callStatus; + TextView callDate; AOHPCTCSeekBar dialAOHPCTCSeekBar; public CallLogViewHolder(@NonNull View itemView) { super(itemView); - phoneNumber = itemView.findViewById(R.id.phone_number); - callStatus = itemView.findViewById(R.id.call_status); - callDate = itemView.findViewById(R.id.call_date); - dialAOHPCTCSeekBar = itemView.findViewById(R.id.aohpctcseekbar_dial); + // Java7 适配:添加强制类型转换 + phoneNumber = (TextView) itemView.findViewById(R.id.phone_number); + callStatus = (TextView) itemView.findViewById(R.id.call_status); + callDate = (TextView) itemView.findViewById(R.id.call_date); + dialAOHPCTCSeekBar = (AOHPCTCSeekBar) itemView.findViewById(R.id.aohpctcseekbar_dial); } } - } diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/adapters/ContactAdapter.java b/contacts/src/main/java/cc/winboll/studio/contacts/adapters/ContactAdapter.java index b58f75e..f213121 100644 --- a/contacts/src/main/java/cc/winboll/studio/contacts/adapters/ContactAdapter.java +++ b/contacts/src/main/java/cc/winboll/studio/contacts/adapters/ContactAdapter.java @@ -1,10 +1,5 @@ package cc.winboll.studio.contacts.adapters; -/** - * @Author ZhanGSKen - * @Date 2025/02/26 13:35:44 - * @Describe ContactAdapter - */ import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; @@ -20,111 +15,142 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import cc.winboll.studio.contacts.R; -import cc.winboll.studio.contacts.beans.ContactModel; +import cc.winboll.studio.contacts.model.ContactModel; import cc.winboll.studio.contacts.utils.ContactUtils; import cc.winboll.studio.libaes.views.AOHPCTCSeekBar; +import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.libappbase.ToastUtils; import java.util.List; +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/02/26 13:35:44 + * @Describe 联系人列表适配器 + */ public class ContactAdapter extends RecyclerView.Adapter { + // ====================== 常量定义区 ====================== public static final String TAG = "ContactAdapter"; + // 移除未使用的 REQUEST_CALL_PHONE 常量,精简冗余代码 - private static final int REQUEST_CALL_PHONE = 1; - + // ====================== 成员变量区 ====================== + private Context mContext; private List contactList; - Context mContext; + // ====================== 构造函数区 ====================== public ContactAdapter(Context context, List contactList) { - mContext = context; + LogUtils.d(TAG, "ContactAdapter: 初始化适配器,联系人数量=" + contactList.size()); + this.mContext = context; this.contactList = contactList; } + // ====================== RecyclerView 重写方法区 ====================== @NonNull @Override public ContactViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + LogUtils.d(TAG, "onCreateViewHolder: 创建联系人列表项ViewHolder"); View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_contact, parent, false); return new ContactViewHolder(view); } @Override public void onBindViewHolder(@NonNull ContactViewHolder holder, int position) { + LogUtils.d(TAG, "onBindViewHolder: 绑定联系人列表项数据,position=" + position); final ContactModel contact = contactList.get(position); - holder.llPhoneNumberMain.setOnLongClickListener(new View.OnLongClickListener() { - @Override - public boolean onLongClick(View p1) { - // 弹出复制菜单 - PopupMenu menu = new PopupMenu(mContext, holder.llPhoneNumberMain); - //加载菜单资源 - menu.getMenuInflater().inflate(R.menu.toolbar_contact_phonenumber, menu.getMenu()); - //设置点击事件的响应 - menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem menuItem) { - int nItemId = menuItem.getItemId(); - if (nItemId == R.id.item_contact_phonenumber_copy) { - // Gets a handle to the clipboard service. - ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE); - // Creates a new text clip to put on the clipboard - ClipData clip = ClipData.newPlainText("simple text", contact.getNumber()); - // Set the clipboard's primary clip. - clipboard.setPrimaryClip(clip); - Toast.makeText(mContext, "Copy to clipboard.", Toast.LENGTH_SHORT).show(); - } else if (nItemId == R.id.item_calllog_phonenumber_edit_contact) { - //ToastUtils.show("Test"); - Long nContactId = ContactUtils.getContactIdByPhone(mContext, contact.getNumber()); - //ToastUtils.show(String.format("%d", nContactId)); - ContactUtils.jumpToEditContact(mContext, contact.getNumber(), nContactId); - } - return true; - } - }); - //一定要调用show()来显示弹出式菜单 - menu.show(); - - return true; - } - }); + // 绑定联系人名称与号码 holder.contactName.setText(contact.getName()); holder.contactNumber.setText(contact.getNumber()); - // 初始化拉动后拨号控件 - holder.dialAOHPCTCSeekBar.setThumb(holder.itemView.getContext().getDrawable(R.drawable.ic_call)); - holder.dialAOHPCTCSeekBar.setBlurRightDP(80); - holder.dialAOHPCTCSeekBar.setThumbOffset(0); - holder.dialAOHPCTCSeekBar.setOnOHPCListener( - new AOHPCTCSeekBar.OnOHPCListener(){ - @Override - public void onOHPCommit() { - String phoneNumber = contact.getNumber().replaceAll("\\s", ""); - ToastUtils.show(phoneNumber); - Intent intent = new Intent(Intent.ACTION_CALL); - intent.setData(android.net.Uri.parse("tel:" + phoneNumber)); - // 添加 FLAG_ACTIVITY_NEW_TASK 标志 - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - holder.itemView.getContext().startActivity(intent); - } - }); + // 长按联系人条目弹出操作菜单 + holder.llPhoneNumberMain.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + showContactPopupMenu(holder.llPhoneNumberMain, contact); + return true; + } + }); + + // 初始化滑动拨号SeekBar + initDialSeekBar(holder.dialAOHPCTCSeekBar, contact); } @Override public int getItemCount() { - return contactList.size(); + // 增加空指针判断,避免空列表崩溃 + return contactList == null ? 0 : contactList.size(); } + // ====================== 私有工具方法区 ====================== + /** + * 显示联系人操作弹窗菜单 + */ + private void showContactPopupMenu(View anchorView, final ContactModel contact) { + LogUtils.d(TAG, "showContactPopupMenu: 弹出联系人操作菜单"); + PopupMenu menu = new PopupMenu(mContext, anchorView); + menu.getMenuInflater().inflate(R.menu.toolbar_contact_phonenumber, menu.getMenu()); + + menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem menuItem) { + int itemId = menuItem.getItemId(); + if (itemId == R.id.item_contact_phonenumber_copy) { + // 复制联系人号码到剪贴板 + ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clip = ClipData.newPlainText("contact_phone", contact.getNumber()); + clipboard.setPrimaryClip(clip); + Toast.makeText(mContext, "Copy to clipboard.", Toast.LENGTH_SHORT).show(); + LogUtils.d(TAG, "showContactPopupMenu: 联系人号码" + contact.getNumber() + "已复制到剪贴板"); + } else if (itemId == R.id.item_calllog_phonenumber_edit_contact) { + // 跳转到编辑联系人页面 + Long contactId = ContactUtils.getContactIdByPhone(mContext, contact.getNumber()); + ContactUtils.jumpToEditContact(mContext, contact.getNumber(), contactId); + LogUtils.d(TAG, "showContactPopupMenu: 跳转编辑联系人页面,号码=" + contact.getNumber() + ",ID=" + contactId); + } + return true; + } + }); + menu.show(); + } + + /** + * 初始化滑动拨号SeekBar + */ + private void initDialSeekBar(AOHPCTCSeekBar seekBar, final ContactModel contact) { + LogUtils.d(TAG, "initDialSeekBar: 初始化滑动拨号控件"); + seekBar.setThumb(seekBar.getContext().getDrawable(R.drawable.ic_call)); + seekBar.setBlurRightDP(80); + seekBar.setThumbOffset(0); + + seekBar.setOnOHPCListener(new AOHPCTCSeekBar.OnOHPCListener() { + @Override + public void onOHPCommit() { + String phoneNumber = contact.getNumber().replaceAll("\\s", ""); + LogUtils.d(TAG, "initDialSeekBar: 滑动拨号触发,号码=" + phoneNumber); + ToastUtils.show(phoneNumber); + + Intent intent = new Intent(Intent.ACTION_CALL); + intent.setData(android.net.Uri.parse("tel:" + phoneNumber)); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(intent); + } + }); + } + + // ====================== ViewHolder 内部类 ====================== public class ContactViewHolder extends RecyclerView.ViewHolder { - LinearLayout llPhoneNumberMain; + LinearLayout llPhoneNumberMain; TextView contactName; TextView contactNumber; AOHPCTCSeekBar dialAOHPCTCSeekBar; public ContactViewHolder(@NonNull View itemView) { super(itemView); - llPhoneNumberMain = itemView.findViewById(R.id.itemcontactLinearLayout1); - contactName = itemView.findViewById(R.id.contact_name); - contactNumber = itemView.findViewById(R.id.contact_number); - dialAOHPCTCSeekBar = itemView.findViewById(R.id.aohpctcseekbar_dial); + // Java7 适配:添加强制类型转换 + llPhoneNumberMain = (LinearLayout) itemView.findViewById(R.id.itemcontactLinearLayout1); + contactName = (TextView) itemView.findViewById(R.id.contact_name); + contactNumber = (TextView) itemView.findViewById(R.id.contact_number); + dialAOHPCTCSeekBar = (AOHPCTCSeekBar) itemView.findViewById(R.id.aohpctcseekbar_dial); } } } diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/adapters/ImagePagerAdapter.java b/contacts/src/main/java/cc/winboll/studio/contacts/adapters/ImagePagerAdapter.java deleted file mode 100644 index c65e35d..0000000 --- a/contacts/src/main/java/cc/winboll/studio/contacts/adapters/ImagePagerAdapter.java +++ /dev/null @@ -1,14 +0,0 @@ -package cc.winboll.studio.contacts.adapters; - -/** - * @Author ZhanGSKen - * @Date 2025/02/20 14:20:38 - * @Describe ImagePagerAdapter - */ -public class ImagePagerAdapter { - - public static final String TAG = "ImagePagerAdapter"; - - - -} \ No newline at end of file diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/adapters/PhoneConnectRuleAdapter.java b/contacts/src/main/java/cc/winboll/studio/contacts/adapters/PhoneConnectRuleAdapter.java index 864ef7e..f135346 100644 --- a/contacts/src/main/java/cc/winboll/studio/contacts/adapters/PhoneConnectRuleAdapter.java +++ b/contacts/src/main/java/cc/winboll/studio/contacts/adapters/PhoneConnectRuleAdapter.java @@ -1,10 +1,5 @@ package cc.winboll.studio.contacts.adapters; -/** - * @Author ZhanGSKen - * @Date 2025/03/02 17:27:41 - * @Describe PhoneConnectRuleAdapter - */ import android.content.Context; import android.view.LayoutInflater; import android.view.View; @@ -17,226 +12,230 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import cc.winboll.studio.contacts.R; -import cc.winboll.studio.contacts.beans.PhoneConnectRuleModel; +import cc.winboll.studio.contacts.model.PhoneConnectRuleModel; import cc.winboll.studio.contacts.dun.Rules; import cc.winboll.studio.contacts.views.LeftScrollView; import cc.winboll.studio.libaes.dialogs.YesNoAlertDialog; +import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.libappbase.ToastUtils; import java.util.ArrayList; import java.util.List; +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/03/02 17:27:41 + * @Describe 通话规则列表适配器,支持简单查看/编辑两种视图切换 + */ public class PhoneConnectRuleAdapter extends RecyclerView.Adapter { + // ====================== 常量定义区 ====================== public static final String TAG = "PhoneConnectRuleAdapter"; - private static final int VIEW_TYPE_SIMPLE = 0; private static final int VIEW_TYPE_EDIT = 1; + private static final String NULL_RULE_TEXT = "[NULL]"; - private Context context; - private List ruleList; + // ====================== 成员变量区 ====================== + private Context mContext; + private List mRuleList; + // ====================== 构造函数区 ====================== public PhoneConnectRuleAdapter(Context context, List ruleList) { - this.context = context; - this.ruleList = ruleList; + LogUtils.d(TAG, "PhoneConnectRuleAdapter: 初始化适配器,规则数量=" + ruleList.size()); + this.mContext = context; + this.mRuleList = ruleList; } + // ====================== RecyclerView 重写方法区 ====================== @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - LayoutInflater inflater = LayoutInflater.from(context); + LayoutInflater inflater = LayoutInflater.from(mContext); if (viewType == VIEW_TYPE_SIMPLE) { + LogUtils.d(TAG, "onCreateViewHolder: 创建简单视图ViewHolder"); View view = inflater.inflate(R.layout.view_phone_connect_rule_simple, parent, false); return new SimpleViewHolder(parent, view); } else { + LogUtils.d(TAG, "onCreateViewHolder: 创建编辑视图ViewHolder"); View view = inflater.inflate(R.layout.view_phone_connect_rule, parent, false); - return new EditViewHolder(parent, view); + return new EditViewHolder(view); } } @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, final int position) { - final PhoneConnectRuleModel model = ruleList.get(position); + final PhoneConnectRuleModel model = mRuleList.get(position); + LogUtils.d(TAG, "onBindViewHolder: 绑定规则数据,position=" + position + ",视图类型=" + getItemViewType(position)); + if (holder instanceof SimpleViewHolder) { - final SimpleViewHolder simpleViewHolder = (SimpleViewHolder) holder; - String szView = model.getRuleText().trim().equals("") ?"[NULL]": model.getRuleText(); - simpleViewHolder.tvRuleText.setText(szView); - simpleViewHolder.checkBoxAllow.setChecked(model.isAllowConnection()); - simpleViewHolder.checkBoxAllow.setEnabled(false); - simpleViewHolder.checkBoxEnable.setChecked(model.isEnable()); - simpleViewHolder.checkBoxEnable.setEnabled(false); - simpleViewHolder.scrollView.setOnActionListener(new LeftScrollView.OnActionListener(){ - - @Override - public void onUp() { - ArrayList list = Rules.getInstance(context).getPhoneBlacRuleBeanList(); - if (position > 0) { - ToastUtils.show("onUp"); - simpleViewHolder.scrollView.smoothScrollTo(0, 0); -// PhoneConnectRuleModel newBean = new PhoneConnectRuleModel(); -// newBean.setRuleText(list.get(position).getRuleText()); -// newBean.setIsAllowConnection(list.get(position).isAllowConnection()); -// newBean.setIsEnable(list.get(position).isEnable()); -// newBean.setIsSimpleView(list.get(position).isSimpleView()); - list.add(position - 1, list.get(position)); - list.remove(position + 1); - Rules.getInstance(context).saveRules(); - notifyDataSetChanged(); - } - } - - @Override - public void onDown() { - ArrayList list = Rules.getInstance(context).getPhoneBlacRuleBeanList(); - if (position < list.size() - 1) { - ToastUtils.show("onDown"); - simpleViewHolder.scrollView.smoothScrollTo(0, 0); -// PhoneConnectRuleModel newBean = new PhoneConnectRuleModel(); -// newBean.setRuleText(list.get(position).getRuleText()); -// newBean.setIsAllowConnection(list.get(position).isAllowConnection()); -// newBean.setIsEnable(list.get(position).isEnable()); -// newBean.setIsSimpleView(list.get(position).isSimpleView()); - list.add(position + 2, list.get(position)); - list.remove(position); - Rules.getInstance(context).saveRules(); - notifyDataSetChanged(); - } - } - - @Override - public void onEdit() { - simpleViewHolder.scrollView.smoothScrollTo(0, 0); - model.setIsSimpleView(false); - notifyDataSetChanged(); - //notifyItemChanged(position); - } - - @Override - public void onDelete() { - YesNoAlertDialog.show(simpleViewHolder.scrollView.getContext(), "删除确认", "是否删除该通话规则?", new YesNoAlertDialog.OnDialogResultListener(){ - - @Override - public void onYes() { - simpleViewHolder.scrollView.smoothScrollTo(0, 0); - model.setIsSimpleView(true); - ArrayList list = Rules.getInstance(context).getPhoneBlacRuleBeanList(); - list.remove(position); - Rules.getInstance(context).saveRules(); - notifyDataSetChanged(); - //notifyItemChanged(position); - } - - @Override - public void onNo() { - } - }); - - } - }); -// simpleViewHolder.editButton.setOnClickListener(new View.OnClickListener() { -// @Override -// public void onClick(View v) { -// model.setIsSimpleView(false); -// notifyItemChanged(position); -// } -// }); -// simpleViewHolder.deleteButton.setOnClickListener(new View.OnClickListener() { -// @Override -// public void onClick(View v) { -// model.setIsSimpleView(false); -// ArrayList list = Rules.getInstance(context).getPhoneBlacRuleBeanList(); -// list.remove(position); -// Rules.getInstance(context).saveRules(); -// notifyItemChanged(position); -// } -// }); -// // 触摸事件处理 -// simpleViewHolder.contentLayout.setOnTouchListener(new View.OnTouchListener() { -// @Override -// public boolean onTouch(View v, MotionEvent event) { -// switch (event.getAction()) { -// case MotionEvent.ACTION_DOWN: -// simpleViewHolder.startX = event.getX(); -// simpleViewHolder.isSwiping = true; -// break; -// case MotionEvent.ACTION_MOVE: -// if (simpleViewHolder.isSwiping) { -// float deltaX = simpleViewHolder.startX - event.getX(); -// if (deltaX > 0) { // 左滑 -// float translationX = Math.max(-simpleViewHolder.actionLayout.getWidth(), -deltaX); -// simpleViewHolder.contentLayout.setTranslationX(translationX); -// simpleViewHolder.actionLayout.setVisibility(View.VISIBLE); -// } -// } -// break; -// case MotionEvent.ACTION_UP: -// simpleViewHolder.isSwiping = false; -// if (simpleViewHolder.contentLayout.getTranslationX() < -simpleViewHolder.actionLayout.getWidth() / 2) { -// // 保持按钮显示 -// simpleViewHolder.contentLayout.setTranslationX(-actionLayout.getWidth()); -// } else { -// // 恢复原状 -// simpleViewHolder.contentLayout.animate().translationX(0).setDuration(200).start(); -// simpleViewHolder.actionLayout.setVisibility(View.INVISIBLE); -// } -// break; -// } -// return true; -// } -// }); + bindSimpleViewHolder((SimpleViewHolder) holder, model, position); } else if (holder instanceof EditViewHolder) { - final EditViewHolder editViewHolder = (EditViewHolder) holder; - editViewHolder.editText.setText(model.getRuleText()); - editViewHolder.checkBoxAllow.setChecked(model.isAllowConnection()); - editViewHolder.checkBoxEnable.setChecked(model.isEnable()); - editViewHolder.buttonConfirm.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - model.setRuleText(editViewHolder.editText.getText().toString()); - model.setIsAllowConnection(editViewHolder.checkBoxAllow.isChecked()); - model.setIsEnable(editViewHolder.checkBoxEnable.isChecked()); - model.setIsSimpleView(true); - Rules.getInstance(context).saveRules(); - notifyItemChanged(position); - Toast.makeText(context, "保存成功", Toast.LENGTH_SHORT).show(); - } - }); + bindEditViewHolder((EditViewHolder) holder, model, position); } } @Override public int getItemCount() { - return ruleList.size(); + return mRuleList == null ? 0 : mRuleList.size(); } @Override public int getItemViewType(int position) { - PhoneConnectRuleModel model = ruleList.get(position); - // 这里可以根据模型的状态来决定视图类型,简单起见,假设点击按钮后进入编辑视图 - return model.isSimpleView() ? VIEW_TYPE_SIMPLE : VIEW_TYPE_EDIT; + return mRuleList.get(position).isSimpleView() ? VIEW_TYPE_SIMPLE : VIEW_TYPE_EDIT; } + // ====================== 私有视图绑定方法区 ====================== + /** + * 绑定简单视图数据 + */ + private void bindSimpleViewHolder(final SimpleViewHolder holder, final PhoneConnectRuleModel model, final int position) { + // 绑定规则文本,空值显示[NULL] + String ruleText = model.getRuleText().trim().isEmpty() ? NULL_RULE_TEXT : model.getRuleText().trim(); + holder.tvRuleText.setText(ruleText); + // 设置复选框状态并禁用编辑 + holder.checkBoxAllow.setChecked(model.isAllowConnection()); + holder.checkBoxAllow.setEnabled(false); + holder.checkBoxEnable.setChecked(model.isEnable()); + holder.checkBoxEnable.setEnabled(false); + + // 设置左滑操作监听 + holder.scrollView.setOnActionListener(new LeftScrollView.OnActionListener() { + @Override + public void onUp() { + LogUtils.d(TAG, "onUp: 规则上移,position=" + position); + moveRuleUp(position); + holder.scrollView.smoothScrollTo(0, 0); + } + + @Override + public void onDown() { + LogUtils.d(TAG, "onDown: 规则下移,position=" + position); + moveRuleDown(position); + holder.scrollView.smoothScrollTo(0, 0); + } + + @Override + public void onEdit() { + LogUtils.d(TAG, "onEdit: 切换到编辑视图,position=" + position); + model.setIsSimpleView(false); + notifyItemChanged(position); + holder.scrollView.smoothScrollTo(0, 0); + } + + @Override + public void onDelete() { + LogUtils.d(TAG, "onDelete: 触发规则删除确认,position=" + position); + showDeleteConfirmDialog(holder.scrollView.getContext(), model, position); + } + }); + } + + /** + * 绑定编辑视图数据 + */ + private void bindEditViewHolder(final EditViewHolder holder, final PhoneConnectRuleModel model, final int position) { + // 绑定规则文本到输入框 + holder.editText.setText(model.getRuleText()); + // 绑定复选框状态 + holder.checkBoxAllow.setChecked(model.isAllowConnection()); + holder.checkBoxEnable.setChecked(model.isEnable()); + + // 确认按钮点击事件 + holder.buttonConfirm.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + String newRuleText = holder.editText.getText().toString().trim(); + model.setRuleText(newRuleText); + model.setIsAllowConnection(holder.checkBoxAllow.isChecked()); + model.setIsEnable(holder.checkBoxEnable.isChecked()); + model.setIsSimpleView(true); + + // 保存规则并刷新视图 + Rules.getInstance(mContext).saveRules(); + notifyItemChanged(position); + Toast.makeText(mContext, "保存成功", Toast.LENGTH_SHORT).show(); + LogUtils.d(TAG, "bindEditViewHolder: 规则保存成功,position=" + position + ",规则内容=" + newRuleText); + } + }); + } + + // ====================== 私有业务工具方法区 ====================== + /** + * 规则上移 + */ + private void moveRuleUp(int position) { + if (position <= 0) { + ToastUtils.show("已到顶部,无法上移"); + return; + } + ArrayList ruleList = Rules.getInstance(mContext).getPhoneBlacRuleBeanList(); + swapRulePosition(ruleList, position, position - 1); + } + + /** + * 规则下移 + */ + private void moveRuleDown(int position) { + ArrayList ruleList = Rules.getInstance(mContext).getPhoneBlacRuleBeanList(); + if (position >= ruleList.size() - 1) { + ToastUtils.show("已到底部,无法下移"); + return; + } + swapRulePosition(ruleList, position, position + 1); + } + + /** + * 交换规则位置 + */ + private void swapRulePosition(ArrayList list, int fromPos, int toPos) { + PhoneConnectRuleModel temp = list.get(fromPos); + list.set(fromPos, list.get(toPos)); + list.set(toPos, temp); + Rules.getInstance(mContext).saveRules(); + notifyDataSetChanged(); + LogUtils.d(TAG, "swapRulePosition: 规则位置交换完成,from=" + fromPos + ",to=" + toPos); + } + + /** + * 显示删除确认弹窗 + */ + private void showDeleteConfirmDialog(Context dialogContext, final PhoneConnectRuleModel model, final int position) { + YesNoAlertDialog.show(dialogContext, "删除确认", "是否删除该通话规则?", new YesNoAlertDialog.OnDialogResultListener() { + @Override + public void onYes() { + ArrayList ruleList = Rules.getInstance(mContext).getPhoneBlacRuleBeanList(); + ruleList.remove(position); + Rules.getInstance(mContext).saveRules(); + notifyDataSetChanged(); + LogUtils.d(TAG, "showDeleteConfirmDialog: 规则删除成功,position=" + position); + } + + @Override + public void onNo() { + LogUtils.d(TAG, "showDeleteConfirmDialog: 用户取消删除规则,position=" + position); + } + }); + } + + // ====================== ViewHolder 内部类区 ====================== static class SimpleViewHolder extends RecyclerView.ViewHolder { - - private final LeftScrollView scrollView; - private final TextView tvRuleText; - CheckBox checkBoxAllow; + LeftScrollView scrollView; + TextView tvRuleText; + CheckBox checkBoxAllow; CheckBox checkBoxEnable; - public SimpleViewHolder(@NonNull ViewGroup parent, @NonNull View itemView) { super(itemView); - scrollView = itemView.findViewById(R.id.scrollView); - LayoutInflater inflater = LayoutInflater.from(itemView.getContext()); - View viewContent = inflater.inflate(R.layout.view_phone_connect_rule_simple_content, parent, false); - tvRuleText = viewContent.findViewById(R.id.ruletext_tv); - checkBoxAllow = viewContent.findViewById(R.id.checkbox_allow); - checkBoxEnable = viewContent.findViewById(R.id.checkbox_enable); - //tvRuleText = new TextView(itemView.getContext()); + scrollView = (LeftScrollView) itemView.findViewById(R.id.scrollView); + // 初始化简单视图内容布局 + LayoutInflater inflater = LayoutInflater.from(itemView.getContext()); + View viewContent = inflater.inflate(R.layout.view_phone_connect_rule_simple_content, parent, false); + tvRuleText = (TextView) viewContent.findViewById(R.id.ruletext_tv); + checkBoxAllow = (CheckBox) viewContent.findViewById(R.id.checkbox_allow); + checkBoxEnable = (CheckBox) viewContent.findViewById(R.id.checkbox_enable); + // 设置内容宽度并添加到滚动视图 scrollView.setContentWidth(parent.getWidth()); - //scrollView.setContentWidth(600); scrollView.addContentLayout(viewContent); } - } static class EditViewHolder extends RecyclerView.ViewHolder { @@ -245,17 +244,14 @@ public class PhoneConnectRuleAdapter extends RecyclerView.Adapter diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/beans/ContactModel.java b/contacts/src/main/java/cc/winboll/studio/contacts/model/ContactModel.java similarity index 98% rename from contacts/src/main/java/cc/winboll/studio/contacts/beans/ContactModel.java rename to contacts/src/main/java/cc/winboll/studio/contacts/model/ContactModel.java index c7e7554..19ae39e 100644 --- a/contacts/src/main/java/cc/winboll/studio/contacts/beans/ContactModel.java +++ b/contacts/src/main/java/cc/winboll/studio/contacts/model/ContactModel.java @@ -1,4 +1,4 @@ -package cc.winboll.studio.contacts.beans; +package cc.winboll.studio.contacts.model; /** * @Author ZhanGSKen&豆包大模型 diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/beans/MainServiceBean.java b/contacts/src/main/java/cc/winboll/studio/contacts/model/MainServiceBean.java similarity index 97% rename from contacts/src/main/java/cc/winboll/studio/contacts/beans/MainServiceBean.java rename to contacts/src/main/java/cc/winboll/studio/contacts/model/MainServiceBean.java index 90fb846..97dc28c 100644 --- a/contacts/src/main/java/cc/winboll/studio/contacts/beans/MainServiceBean.java +++ b/contacts/src/main/java/cc/winboll/studio/contacts/model/MainServiceBean.java @@ -1,4 +1,4 @@ -package cc.winboll.studio.contacts.beans; +package cc.winboll.studio.contacts.model; /** * @Author ZhanGSKen diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/beans/PhoneConnectRuleModel.java b/contacts/src/main/java/cc/winboll/studio/contacts/model/PhoneConnectRuleModel.java similarity index 98% rename from contacts/src/main/java/cc/winboll/studio/contacts/beans/PhoneConnectRuleModel.java rename to contacts/src/main/java/cc/winboll/studio/contacts/model/PhoneConnectRuleModel.java index c27b753..cb0db90 100644 --- a/contacts/src/main/java/cc/winboll/studio/contacts/beans/PhoneConnectRuleModel.java +++ b/contacts/src/main/java/cc/winboll/studio/contacts/model/PhoneConnectRuleModel.java @@ -1,4 +1,4 @@ -package cc.winboll.studio.contacts.beans; +package cc.winboll.studio.contacts.model; /** * @Author ZhanGSKen diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/beans/RingTongBean.java b/contacts/src/main/java/cc/winboll/studio/contacts/model/RingTongBean.java similarity index 97% rename from contacts/src/main/java/cc/winboll/studio/contacts/beans/RingTongBean.java rename to contacts/src/main/java/cc/winboll/studio/contacts/model/RingTongBean.java index 39b2cb7..934d323 100644 --- a/contacts/src/main/java/cc/winboll/studio/contacts/beans/RingTongBean.java +++ b/contacts/src/main/java/cc/winboll/studio/contacts/model/RingTongBean.java @@ -1,4 +1,4 @@ -package cc.winboll.studio.contacts.beans; +package cc.winboll.studio.contacts.model; /** * @Author ZhanGSKen diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/beans/SettingsModel.java b/contacts/src/main/java/cc/winboll/studio/contacts/model/SettingsModel.java similarity index 99% rename from contacts/src/main/java/cc/winboll/studio/contacts/beans/SettingsModel.java rename to contacts/src/main/java/cc/winboll/studio/contacts/model/SettingsModel.java index 94775da..9dda140 100644 --- a/contacts/src/main/java/cc/winboll/studio/contacts/beans/SettingsModel.java +++ b/contacts/src/main/java/cc/winboll/studio/contacts/model/SettingsModel.java @@ -1,4 +1,4 @@ -package cc.winboll.studio.contacts.beans; +package cc.winboll.studio.contacts.model; /** * @Author ZhanGSKen diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/phonecallui/PhoneCallService.java b/contacts/src/main/java/cc/winboll/studio/contacts/phonecallui/PhoneCallService.java index ee7a249..0db920d 100644 --- a/contacts/src/main/java/cc/winboll/studio/contacts/phonecallui/PhoneCallService.java +++ b/contacts/src/main/java/cc/winboll/studio/contacts/phonecallui/PhoneCallService.java @@ -19,7 +19,7 @@ import android.telecom.InCallService; import android.telephony.TelephonyManager; import androidx.annotation.RequiresApi; import cc.winboll.studio.contacts.ActivityStack; -import cc.winboll.studio.contacts.beans.RingTongBean; +import cc.winboll.studio.contacts.model.RingTongBean; import cc.winboll.studio.contacts.dun.Rules; import cc.winboll.studio.contacts.fragments.CallLogFragment; import cc.winboll.studio.libappbase.LogUtils; diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/services/AssistantService.java b/contacts/src/main/java/cc/winboll/studio/contacts/services/AssistantService.java index 4a4fdd7..a402dcf 100644 --- a/contacts/src/main/java/cc/winboll/studio/contacts/services/AssistantService.java +++ b/contacts/src/main/java/cc/winboll/studio/contacts/services/AssistantService.java @@ -12,7 +12,7 @@ import android.content.Intent; import android.content.ServiceConnection; import android.os.Binder; import android.os.IBinder; -import cc.winboll.studio.contacts.beans.MainServiceBean; +import cc.winboll.studio.contacts.model.MainServiceBean; import cc.winboll.studio.contacts.services.MainService; import cc.winboll.studio.libappbase.LogUtils; diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/services/MainService.java b/contacts/src/main/java/cc/winboll/studio/contacts/services/MainService.java index 75c94a9..b89a77f 100644 --- a/contacts/src/main/java/cc/winboll/studio/contacts/services/MainService.java +++ b/contacts/src/main/java/cc/winboll/studio/contacts/services/MainService.java @@ -18,8 +18,8 @@ import android.content.ServiceConnection; import android.media.AudioManager; import android.os.Binder; import android.os.IBinder; -import cc.winboll.studio.contacts.beans.MainServiceBean; -import cc.winboll.studio.contacts.beans.RingTongBean; +import cc.winboll.studio.contacts.model.MainServiceBean; +import cc.winboll.studio.contacts.model.RingTongBean; import cc.winboll.studio.contacts.bobulltoon.TomCat; import cc.winboll.studio.contacts.dun.Rules; import cc.winboll.studio.contacts.handlers.MainServiceHandler; diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/views/DuInfoTextView.java b/contacts/src/main/java/cc/winboll/studio/contacts/views/DuInfoTextView.java index 6d1e9f6..b5e1660 100644 --- a/contacts/src/main/java/cc/winboll/studio/contacts/views/DuInfoTextView.java +++ b/contacts/src/main/java/cc/winboll/studio/contacts/views/DuInfoTextView.java @@ -9,7 +9,7 @@ import android.content.Context; import android.os.Handler; import android.os.Message; import android.widget.TextView; -import cc.winboll.studio.contacts.beans.SettingsModel; +import cc.winboll.studio.contacts.model.SettingsModel; import cc.winboll.studio.contacts.dun.Rules; import cc.winboll.studio.libappbase.LogUtils;