Compare commits

..

10 Commits

Author SHA1 Message Date
ZhanGSKen
0db31c07ba <contacts>APK 1.0.14 release Publish. 2025-03-08 04:37:47 +08:00
ZhanGSKen
87dea88e36 <contacts>APK 1.0.13 release Publish. 2025-03-08 04:37:15 +08:00
ZhanGSKen
5779f195f8 设置UI为拖动拨号方式 2025-03-08 04:36:07 +08:00
ZhanGSKen
02f2d4f0bc <contacts>APK 1.0.12 release Publish. 2025-03-06 21:44:44 +08:00
ZhanGSKen
f6bece28ac 添加通信记录联系人显示 2025-03-06 21:43:50 +08:00
ZhanGSKen
559f1c58ba <contacts>APK 1.0.11 release Publish. 2025-03-06 20:00:52 +08:00
ZhanGSKen
4bb814308b 添加单号码单元测试 2025-03-06 19:59:11 +08:00
ZhanGSKen
05a9fc5275 <contacts>APK 1.0.10 release Publish. 2025-03-05 20:51:08 +08:00
ZhanGSKen
74d5239898 添加规则删除确认框。 2025-03-05 20:49:39 +08:00
ZhanGSKen
948141d5a9 规则编辑列表的项滑动逻辑完成。 2025-03-05 20:41:29 +08:00
19 changed files with 394 additions and 109 deletions

View File

@@ -41,29 +41,41 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.squareup.okhttp3:okhttp:4.4.1'
api fileTree(dir: 'libs', include: ['*.jar'])
// 权限请求框架https://github.com/getActivity/XXPermissions
implementation 'com.github.getActivity:XXPermissions:18.63'
// 下拉控件
implementation 'com.baoyz.pullrefreshlayout:library:1.2.0'
// 拼音搜索
// https://mvnrepository.com/artifact/com.github.open-android/pinyin4j
implementation 'com.github.open-android:pinyin4j:2.5.0'
// SSH
implementation 'com.jcraft:jsch:0.1.55'
// Html 解析
implementation 'org.jsoup:jsoup:1.13.1'
// 二维码类库
implementation 'com.google.zxing:core:3.4.1'
implementation 'com.journeyapps:zxing-android-embedded:3.6.0'
// 应用介绍页类库
implementation 'io.github.medyo:android-about-page:2.0.0'
// 吐司类库
implementation 'com.github.getActivity:ToastUtils:10.5'
// 网络连接类库
implementation 'com.squareup.okhttp3:okhttp:4.4.1'
// Android 类库
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.viewpager:viewpager:1.0.0'
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
implementation 'androidx.vectordrawable:vectordrawable-animated:1.1.0'
implementation 'androidx.fragment:fragment:1.1.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'cc.winboll.studio:libapputils:9.3.2'
implementation 'cc.winboll.studio:libappbase:1.5.6'
implementation 'cc.winboll.studio:libappbase:2.1.3'
implementation 'cc.winboll.studio:libapputils:9.4.2'
implementation 'cc.winboll.studio:libaes:7.6.6'
}

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Wed Mar 05 17:21:57 HKT 2025
stageCount=10
#Sat Mar 08 04:37:47 HKT 2025
stageCount=15
libraryProject=
baseVersion=1.0
publishVersion=1.0.9
publishVersion=1.0.14
buildCount=0
baseBetaVersion=1.0.10
baseBetaVersion=1.0.15

View File

@@ -35,9 +35,7 @@ import cc.winboll.studio.contacts.services.MainService;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.LogView;
import cc.winboll.studio.libapputils.app.IWinBollActivity;
import cc.winboll.studio.libapputils.app.WinBollActivityManager;
import cc.winboll.studio.libapputils.bean.APPInfo;
import cc.winboll.studio.libapputils.view.YesNoAlertDialog;
import com.google.android.material.tabs.TabLayout;
import java.util.ArrayList;
import java.util.List;

View File

@@ -29,17 +29,17 @@ 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.bobulltoon.TomCat;
import cc.winboll.studio.contacts.dun.Rules;
import cc.winboll.studio.contacts.services.MainService;
import cc.winboll.studio.libappbase.IWinBollActivity;
import cc.winboll.studio.libappbase.bean.APPInfo;
import cc.winboll.studio.contacts.views.DuInfoTextView;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libapputils.app.IWinBollActivity;
import cc.winboll.studio.libapputils.bean.APPInfo;
import com.hjq.toast.ToastUtils;
import java.lang.reflect.Field;
import java.util.List;
import cc.winboll.studio.contacts.beans.SettingsModel;
import cc.winboll.studio.contacts.views.DuInfoTextView;
import cc.winboll.studio.libappbase.LogUtils;
public class SettingsActivity extends AppCompatActivity implements IWinBollActivity {

View File

@@ -7,6 +7,7 @@ import cc.winboll.studio.contacts.R;
import cc.winboll.studio.contacts.dun.Rules;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.LogView;
import android.widget.EditText;
/**
* @Author ZhanGSKen@AliYun.Com
@@ -26,6 +27,15 @@ public class UnitTestActivity extends Activity {
logView.start();
}
public void onTestPhone(View view) {
// 开始测试数据
EditText etPhone = findViewById(R.id.phone_et);
Rules rules = Rules.getInstance(this);
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) {
Rules rules = Rules.getInstance(this);

View File

@@ -5,6 +5,7 @@ package cc.winboll.studio.contacts.adapters;
* @Date 2025/02/26 13:09:32
* @Describe CallLogAdapter
*/
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
@@ -15,6 +16,8 @@ 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.utils.ContactUtils;
import cc.winboll.studio.libaes.views.AOHPCTCSeekBar;
import com.hjq.toast.ToastUtils;
import java.text.SimpleDateFormat;
import java.util.List;
@@ -24,8 +27,12 @@ public class CallLogAdapter extends RecyclerView.Adapter<CallLogAdapter.CallLogV
public static final String TAG = "CallLogAdapter";
private List<CallLogModel> callLogList;
ContactUtils mContactUtils;
Context mContext;
public CallLogAdapter(List<CallLogModel> callLogList) {
public CallLogAdapter(Context context, List<CallLogModel> callLogList) {
mContext = context;
this.mContactUtils = ContactUtils.getInstance(mContext);
this.callLogList = callLogList;
}
@@ -39,13 +46,18 @@ public class CallLogAdapter extends RecyclerView.Adapter<CallLogAdapter.CallLogV
@Override
public void onBindViewHolder(@NonNull CallLogViewHolder holder, int position) {
final CallLogModel callLog = callLogList.get(position);
holder.phoneNumber.setText(callLog.getPhoneNumber());
holder.phoneNumber.setText(callLog.getPhoneNumber() + "" + mContactUtils.getContactsName(callLog.getPhoneNumber()));
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.dialButton.setOnClickListener(new View.OnClickListener() {
// 初始化拉动后拨号控件
holder.dialAOHPCTCSeekBar.setThumb(holder.itemView.getContext().getDrawable(R.drawable.ic_call));
holder.dialAOHPCTCSeekBar.setThumbOffset(20);
holder.dialAOHPCTCSeekBar.setOnOHPCListener(
new AOHPCTCSeekBar.OnOHPCListener(){
@Override
public void onClick(View v) {
public void onOHPCommit() {
String phoneNumber = callLog.getPhoneNumber().replaceAll("\\s", "");
ToastUtils.show(phoneNumber);
Intent intent = new Intent(Intent.ACTION_CALL);
@@ -65,15 +77,16 @@ public class CallLogAdapter extends RecyclerView.Adapter<CallLogAdapter.CallLogV
public class CallLogViewHolder extends RecyclerView.ViewHolder {
TextView phoneNumber, callStatus, callDate;
Button dialButton;
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);
dialButton = itemView.findViewById(R.id.dial_button);
dialAOHPCTCSeekBar = itemView.findViewById(R.id.aohpctcseekbar_dial);
}
}
}

View File

@@ -17,6 +17,7 @@ import cc.winboll.studio.contacts.R;
import cc.winboll.studio.contacts.beans.ContactModel;
import com.hjq.toast.ToastUtils;
import java.util.List;
import cc.winboll.studio.libaes.views.AOHPCTCSeekBar;
public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.ContactViewHolder> {
@@ -43,9 +44,13 @@ public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.ContactV
holder.contactName.setText(contact.getName());
holder.contactNumber.setText(contact.getNumber());
holder.dialButton.setOnClickListener(new View.OnClickListener() {
// 初始化拉动后拨号控件
holder.dialAOHPCTCSeekBar.setThumb(holder.itemView.getContext().getDrawable(R.drawable.ic_call));
holder.dialAOHPCTCSeekBar.setThumbOffset(20);
holder.dialAOHPCTCSeekBar.setOnOHPCListener(
new AOHPCTCSeekBar.OnOHPCListener(){
@Override
public void onClick(View v) {
public void onOHPCommit() {
String phoneNumber = contact.getNumber().replaceAll("\\s", "");
ToastUtils.show(phoneNumber);
Intent intent = new Intent(Intent.ACTION_CALL);
@@ -65,13 +70,13 @@ public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.ContactV
public class ContactViewHolder extends RecyclerView.ViewHolder {
TextView contactName;
TextView contactNumber;
Button dialButton;
AOHPCTCSeekBar dialAOHPCTCSeekBar;
public ContactViewHolder(@NonNull View itemView) {
super(itemView);
contactName = itemView.findViewById(R.id.contact_name);
contactNumber = itemView.findViewById(R.id.contact_number);
dialButton = itemView.findViewById(R.id.dial_button);
dialAOHPCTCSeekBar = itemView.findViewById(R.id.aohpctcseekbar_dial);
}
}
}

View File

@@ -25,6 +25,8 @@ import android.widget.LinearLayout;
import android.view.MotionEvent;
import android.widget.HorizontalScrollView;
import cc.winboll.studio.contacts.views.LeftScrollView;
import com.hjq.toast.ToastUtils;
import cc.winboll.studio.libapputils.view.YesNoAlertDialog;
public class PhoneConnectRuleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
@@ -59,9 +61,46 @@ public class PhoneConnectRuleAdapter extends RecyclerView.Adapter<RecyclerView.V
final PhoneConnectRuleModel model = ruleList.get(position);
if (holder instanceof SimpleViewHolder) {
final SimpleViewHolder simpleViewHolder = (SimpleViewHolder) holder;
String szView = model.getRuleText().trim().equals("")?"[NULL]":model.getRuleText();
String szView = model.getRuleText().trim().equals("") ?"[NULL]": model.getRuleText();
simpleViewHolder.tvRuleText.setText(szView);
simpleViewHolder.scrollView.setOnActionListener(new LeftScrollView.OnActionListener(){
@Override
public void onUp() {
ArrayList<PhoneConnectRuleModel> 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<PhoneConnectRuleModel> 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);
@@ -72,13 +111,24 @@ public class PhoneConnectRuleAdapter extends RecyclerView.Adapter<RecyclerView.V
@Override
public void onDelete() {
simpleViewHolder.scrollView.smoothScrollTo(0, 0);
model.setIsSimpleView(true);
ArrayList<PhoneConnectRuleModel> list = Rules.getInstance(context).getPhoneBlacRuleBeanList();
list.remove(position);
Rules.getInstance(context).saveRules();
notifyDataSetChanged();
//notifyItemChanged(position);
YesNoAlertDialog.show(simpleViewHolder.scrollView.getContext(), "删除确认", "是否删除该通话规则?", new YesNoAlertDialog.OnDialogResultListener(){
@Override
public void onYes() {
simpleViewHolder.scrollView.smoothScrollTo(0, 0);
model.setIsSimpleView(true);
ArrayList<PhoneConnectRuleModel> 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() {

View File

@@ -65,7 +65,7 @@ public class CallLogFragment extends Fragment {
super.onViewCreated(view, savedInstanceState);
recyclerView = view.findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
callLogAdapter = new CallLogAdapter(callLogList);
callLogAdapter = new CallLogAdapter(getContext(), callLogList);
recyclerView.setAdapter(callLogAdapter);
if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_CALL_LOG)!= PackageManager.PERMISSION_GRANTED) {

View File

@@ -20,6 +20,7 @@ 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.bobulltoon.TomCat;
import cc.winboll.studio.contacts.dun.Rules;
import cc.winboll.studio.contacts.handlers.MainServiceHandler;
import cc.winboll.studio.contacts.listenphonecall.CallListenerService;
@@ -27,11 +28,12 @@ import cc.winboll.studio.contacts.receivers.MainReceiver;
import cc.winboll.studio.contacts.services.MainService;
import cc.winboll.studio.contacts.threads.MainServiceThread;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.SOS;
import cc.winboll.studio.libappbase.bean.APPSOSBean;
import cc.winboll.studio.libappbase.sos.SOS;
import java.util.Timer;
import java.util.TimerTask;
import cc.winboll.studio.contacts.bobulltoon.TomCat;
import cc.winboll.studio.libappbase.sos.WinBoll;
import cc.winboll.studio.contacts.App;
import cc.winboll.studio.libappbase.sos.APPModel;
public class MainService extends Service {
@@ -128,7 +130,11 @@ public class MainService extends Service {
// 唤醒守护进程
wakeupAndBindAssistant();
// 召唤 WinBoll APP 绑定本服务
SOS.bindToAPPService(this, new APPSOSBean(getPackageName(), MainService.class.getName()));
if (App.isDebuging()) {
WinBoll.bindToAPPBaseBeta(this, MainService.class.getName());
} else {
WinBoll.bindToAPPBase(this, MainService.class.getName());
}
// 初始化服务运行参数
_TomCat = TomCat.getInstance(this);
@@ -234,7 +240,11 @@ public class MainService extends Service {
if (mMainServiceBean.isEnable()) {
// 唤醒守护进程
wakeupAndBindAssistant();
SOS.sosWinBollService(getApplicationContext(), new APPSOSBean(getPackageName(), MainService.class.getName()));
if (App.isDebuging()) {
SOS.sosToAppBase(getApplicationContext(), MainService.class.getName());
} else {
SOS.sosToAppBaseBeta(getApplicationContext(), MainService.class.getName());
}
}
isBound = false;
mAssistantService = null;
@@ -296,7 +306,7 @@ public class MainService extends Service {
LogUtils.d(TAG, "已重启 MainService");
}
}
public static void stopMainServiceAndSaveStatus(Context context) {
LogUtils.d(TAG, "stopMainServiceAndSaveStatus");
MainServiceBean bean = new MainServiceBean();

View File

@@ -6,11 +6,7 @@ package cc.winboll.studio.contacts.threads;
*/
import android.content.Context;
import cc.winboll.studio.contacts.handlers.MainServiceHandler;
import cc.winboll.studio.contacts.services.MainService;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.SOS;
import cc.winboll.studio.libappbase.bean.APPSOSBean;
import com.hjq.toast.ToastUtils;
import java.lang.ref.WeakReference;
public class MainServiceThread extends Thread {

View File

@@ -0,0 +1,93 @@
package cc.winboll.studio.contacts.utils;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.provider.ContactsContract;
import java.util.HashMap;
import java.util.Map;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/06 21:08:16
* @Describe ContactUtils
*/
public class ContactUtils {
public static final String TAG = "ContactUtils";
Map<String, String> contactMap = new HashMap<>();
static volatile ContactUtils _ContactUtils;
Context mContext;
ContactUtils(Context context) {
mContext = context;
relaodContacts();
}
public synchronized static ContactUtils getInstance(Context context) {
if (_ContactUtils == null) {
_ContactUtils = new ContactUtils(context);
}
return _ContactUtils;
}
public void relaodContacts() {
readContacts();
}
private void readContacts() {
contactMap.clear();
ContentResolver contentResolver = mContext.getContentResolver();
Cursor cursor = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null, null, null, null);
if (cursor != null) {
while (cursor.moveToNext()) {
String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
//Map<String, String> contactMap = new HashMap<>();
contactMap.put(formatToSimplePhoneNumber(phoneNumber), displayName);
}
cursor.close();
}
// 此时 contactList 就是存储联系人信息的 Map 列表
}
public String getContactsName(String phone) {
String result = contactMap.get(formatToSimplePhoneNumber(phone));
return result == null ? "[NoInContacts]" : result;
}
// static String getSimplePhone(String phone) {
// return phone.replaceAll("[+\\s]", "");
// }
public static String formatToSimplePhoneNumber(String number) {
// 去除所有空格和非数字字符
return number.replaceAll("[^0-9]", "");
}
public static String getDisplayNameByPhone(Context context, String phoneNumber) {
String displayName = null;
ContentResolver resolver = context.getContentResolver();
String[] projection = {ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME};
Cursor cursor = resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projection, ContactsContract.CommonDataKinds.Phone.NUMBER + "=?", new String[]{formatToSimplePhoneNumber(phoneNumber)}, null);
if (cursor!= null && cursor.moveToFirst()) {
displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
cursor.close();
}
return displayName;
}
public static String formatToSpacePhoneNumber(String simpleNumber) {
// 去除所有空格和非数字字符
StringBuilder sbSpaceNumber = new StringBuilder();
String regex = "^1[0-9]{10}$";
if(simpleNumber.matches(regex)) {
sbSpaceNumber.append(simpleNumber.substring(0,2));
sbSpaceNumber.append(" ");
sbSpaceNumber.append(simpleNumber.substring(3,6));
sbSpaceNumber.append(" ");
sbSpaceNumber.append(simpleNumber.substring(7,10));
}
return sbSpaceNumber.toString();
}
}

View File

@@ -15,7 +15,6 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import cc.winboll.studio.contacts.R;
import cc.winboll.studio.libappbase.LogUtils;
import android.util.TypedValue;
public class LeftScrollView extends HorizontalScrollView {
@@ -26,8 +25,12 @@ public class LeftScrollView extends HorizontalScrollView {
private TextView textView;
private Button editButton;
private Button deleteButton;
private float mLastX;
private Button upButton;
private Button downButton;
private float mStartX;
private float mEndX;
private boolean isScrolling = false;
private int nScrollAcceptSize;
public LeftScrollView(Context context) {
super(context);
@@ -52,6 +55,7 @@ public class LeftScrollView extends HorizontalScrollView {
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) contentLayout.getLayoutParams();
layoutParams.width = contentWidth;
contentLayout.setLayoutParams(layoutParams);
}
private void init() {
@@ -69,6 +73,10 @@ public class LeftScrollView extends HorizontalScrollView {
editButton = viewMain.findViewById(R.id.edit_btn);
// 创建删除按钮
deleteButton = viewMain.findViewById(R.id.delete_btn);
// 向上按钮
upButton = viewMain.findViewById(R.id.up_btn);
// 向下按钮
downButton = viewMain.findViewById(R.id.down_btn);
// 编辑按钮点击事件
editButton.setOnClickListener(new OnClickListener() {
@@ -89,6 +97,25 @@ public class LeftScrollView extends HorizontalScrollView {
}
}
});
// 编辑按钮点击事件
upButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (onActionListener != null) {
onActionListener.onUp();
}
}
});
// 删除按钮点击事件
downButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (onActionListener != null) {
onActionListener.onDown();
}
}
});
}
@Override
@@ -96,53 +123,40 @@ public class LeftScrollView extends HorizontalScrollView {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
LogUtils.d(TAG, "ACTION_DOWN");
mLastX = event.getX();
isScrolling = false;
mStartX = event.getX();
// isScrolling = false;
break;
case MotionEvent.ACTION_MOVE:
//LogUtils.d(TAG, "ACTION_MOVE");
float currentX = event.getX();
float deltaX = mLastX - currentX;
mLastX = currentX;
if (Math.abs(deltaX) > 0) {
isScrolling = true;
}
// float currentX = event.getX();
// float deltaX = mStartX - currentX;
// //mLastX = currentX;
// if (Math.abs(deltaX) > 0) {
// isScrolling = true;
// }
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
LogUtils.d(TAG, "ACTION_UP");
if (isScrolling) {
LogUtils.d(TAG, String.format("isScrolling \ngetScrollX() %d\neditButton.getWidth() %d", getScrollX(), editButton.getWidth()));
int scrollX = getScrollX();
if (scrollX > editButton.getWidth()) {
// 获取HorizontalScrollView的子视图
View childView = getChildAt(0);
if (childView != null) {
// 计算需要滑动到最右边的距离
int scrollToX = childView.getWidth() - getWidth();
// 确保滑动距离不小于0
final int scrollToX2 = Math.max(0, scrollToX);
// 平滑滑动到最右边
post(new Runnable() {
@Override
public void run() {
smoothScrollTo(scrollToX2, 0);
LogUtils.d(TAG, "smoothScrollTo(0, 0);");
}
});
LogUtils.d(TAG, "smoothScrollTo(scrollToX, 0);");
if (getScrollX() > 0) {
LogUtils.d(TAG, "ACTION_UP");
mEndX = event.getX();
LogUtils.d(TAG, String.format("mStartX %f, mEndX %f", mStartX, mEndX));
if (mEndX < mStartX) {
LogUtils.d(TAG, String.format("mEndX >= mStartX \ngetScrollX() %d", getScrollX()));
//if (getScrollX() > editButton.getWidth()) {
if (Math.abs(mStartX - mEndX) > editButton.getWidth()) {
smoothScrollToRight();
} else {
smoothScrollToLeft();
}
} else {
// 恢复原状
// 在手指抬起时,使用 post 方法调用 smoothScrollTo(0, 0)
post(new Runnable() {
@Override
public void run() {
smoothScrollTo(0, 0);
LogUtils.d(TAG, "smoothScrollTo(0, 0);");
}
});
//toolLayout.setTranslationX(0);
LogUtils.d(TAG, String.format("mEndX >= mStartX \ngetScrollX() %d", getScrollX()));
//if (getScrollX() > deleteButton.getWidth()) {
if (Math.abs(mEndX - mStartX) > deleteButton.getWidth()) {
smoothScrollToLeft();
} else {
smoothScrollToRight();
}
}
}
break;
@@ -150,6 +164,40 @@ public class LeftScrollView extends HorizontalScrollView {
return super.onTouchEvent(event);
}
void smoothScrollToRight() {
mEndX = 0;
mStartX = 0;
View childView = getChildAt(0);
if (childView != null) {
// 计算需要滑动到最右边的距离
int scrollToX = childView.getWidth() - getWidth();
// 确保滑动距离不小于0
final int scrollToX2 = Math.max(0, scrollToX);
// 平滑滑动到最右边
post(new Runnable() {
@Override
public void run() {
smoothScrollTo(scrollToX2, 0);
LogUtils.d(TAG, "smoothScrollTo(0, 0);");
}
});
LogUtils.d(TAG, "smoothScrollTo(scrollToX, 0);");
}
}
void smoothScrollToLeft() {
mEndX = 0;
mStartX = 0;
// 在手指抬起时,使用 post 方法调用 smoothScrollTo(0, 0)
post(new Runnable() {
@Override
public void run() {
smoothScrollTo(0, 0);
LogUtils.d(TAG, "smoothScrollTo(0, 0);");
}
});
}
// 设置文本内容
public void setText(CharSequence text) {
textView.setText(text);
@@ -159,6 +207,8 @@ public class LeftScrollView extends HorizontalScrollView {
public interface OnActionListener {
void onEdit();
void onDelete();
void onUp();
void onDown();
}
private OnActionListener onActionListener;

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="#ff000000"
android:pathData="M6.62,10.79C8.06,13.62 10.38,15.94 13.21,17.38L15.41,15.18C15.69,14.9 16.08,14.82 16.43,14.93C17.55,15.3 18.75,15.5 20,15.5A1,1 0,0 1,21 16.5V20A1,1 0,0 1,20 21A17,17 0,0 1,3 4A1,1 0,0 1,4 3H7.5A1,1 0,0 1,8.5 4C8.5,5.25 8.7,6.45 9.07,7.57C9.18,7.92 9.1,8.31 8.82,8.59L6.62,10.79Z"/>
</vector>

View File

@@ -6,9 +6,11 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<HorizontalScrollView
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:gravity="right">
<Button
android:layout_width="wrap_content"
@@ -16,7 +18,34 @@
android:text="Test Main"
android:onClick="onTestMain"/>
</HorizontalScrollView>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试号码:"/>
<EditText
android:layout_width="0dp"
android:inputType="phone"
android:layout_height="wrap_content"
android:ems="10"
android:layout_weight="1.0"
android:id="@+id/phone_et"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test Phone"
android:onClick="onTestPhone"/>
</LinearLayout>
<cc.winboll.studio.libappbase.LogView
android:layout_width="match_parent"

View File

@@ -3,13 +3,13 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:padding="16dp">
<TextView
android:id="@+id/phone_number"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textStyle="bold" />
@@ -28,12 +28,10 @@
android:textSize="14sp"
android:layout_marginTop="4dp" />
<Button
android:id="@+id/dial_button"
android:layout_width="wrap_content"
<cc.winboll.studio.libaes.views.AOHPCTCSeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Dial"
android:layout_marginTop="8dp"/>
android:id="@+id/aohpctcseekbar_dial"/>
</LinearLayout>

View File

@@ -20,12 +20,10 @@
android:textSize="14sp"
android:layout_marginTop="4dp"/>
<Button
android:id="@+id/dial_button"
android:layout_width="wrap_content"
<cc.winboll.studio.libaes.views.AOHPCTCSeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Dial"
android:layout_marginTop="8dp"/>
android:id="@+id/aohpctcseekbar_dial"/>
</LinearLayout>

View File

@@ -30,7 +30,18 @@
android:layout_height="wrap_content"
android:text="编辑"
android:background="@color/blue" />
<Button
android:id="@+id/up_btn"
android:layout_width="40dp"
android:layout_height="wrap_content"
android:text="△"
android:background="@color/green" />
<Button
android:id="@+id/down_btn"
android:layout_width="40dp"
android:layout_height="wrap_content"
android:text="▽"
android:background="@color/green" />
<Button
android:id="@+id/delete_btn"
android:layout_width="80dp"

View File

@@ -5,6 +5,7 @@
<color name="colorPrimaryDark">#FF002B57</color>
<color name="colorAccent">#FF80BFFF</color>
<color name="blue">#FF379AFF</color>
<color name="green">#FF69E551</color>
<color name="red">#FFE55151</color>
<color name="white">#FFFFFFFF</color>
<color name="lightgray">#FFE0E0E0</color>