From cdba188a91c720941ba49b886f259a992c77a32a Mon Sep 17 00:00:00 2001 From: luozheng <1732036298@qq.com> Date: Tue, 2 Dec 2025 16:21:32 +0800 Subject: [PATCH] =?utf8?q?=E9=9B=B7=E9=B8=9F=EF=BC=9A=E8=93=9D=E7=89=99?= =?utf8?q?=E5=88=97=E8=A1=A8=E6=B7=BB=E5=8A=A0=E8=BF=9E=E6=8E=A5=E4=B8=AD?= =?utf8?q?=E5=8A=A8=E7=94=BB=EF=BC=8C=E4=BC=98=E5=8C=96=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../nativeui/bluetooth/src/BluetoothModel.cpp | 57 ++++++- .../bluetooth/src/Ln_Bluetooth_apiC.cpp | 6 - .../include/ThunderBirdBlueListAdapter.h | 6 + .../thunderbird/include/ThunderBirdBlueView.h | 63 ------- .../src/ThunderBirdBlueListAdapter.cpp | 154 +++++++++++++++++- .../thunderbird/src/ThunderBirdBlueView.cpp | 105 +++--------- .../thunderbird/src/ThunderBirdModel.cpp | 28 +++- .../thunderbird/src/ThunderBirdPresenter.cpp | 2 + 8 files changed, 258 insertions(+), 163 deletions(-) diff --git a/code/sdk/application/wearable/ln/nativeapp/nativeui/bluetooth/src/BluetoothModel.cpp b/code/sdk/application/wearable/ln/nativeapp/nativeui/bluetooth/src/BluetoothModel.cpp index eab84badd..514c98b7f 100644 --- a/code/sdk/application/wearable/ln/nativeapp/nativeui/bluetooth/src/BluetoothModel.cpp +++ b/code/sdk/application/wearable/ln/nativeapp/nativeui/bluetooth/src/BluetoothModel.cpp @@ -544,6 +544,9 @@ void BluetoothModel::SetAdvStartState(bool state) // 连接远程设备 int BluetoothModel::ConnectRemoteDevice(const bd_addr_t *addr) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ConnectRemoteDevice: 准备连接设备 addr=%02x%02x%02x%02x%02x%02x", + addr->addr[5], addr->addr[4], addr->addr[3], + addr->addr[2], addr->addr[1], addr->addr[0]); /* 恢厂后耳机连接要开启BT广播否则会导致AVRCP无法音量控制 */ bool ret = gap_br_set_bt_scan_mode(GAP_SCAN_MODE_CONNECTABLE, 60); if (!ret) { @@ -552,6 +555,9 @@ int BluetoothModel::ConnectRemoteDevice(const bd_addr_t *addr) errcode_t retVal = gap_connect_remote_device(addr); WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "连接远程设备 ret = 0x%x", retVal); (void)memcpy_s(&remoteConnectAddr, sizeof(bd_addr_t), addr, sizeof(bd_addr_t)); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ConnectRemoteDevice: remoteConnectAddr已设置为 %02x%02x%02x%02x%02x%02x", + remoteConnectAddr.addr[5], remoteConnectAddr.addr[4], remoteConnectAddr.addr[3], + remoteConnectAddr.addr[2], remoteConnectAddr.addr[1], remoteConnectAddr.addr[0]); return retVal; } @@ -974,6 +980,37 @@ void BluetoothModel::BtGapAclStateChangedHandle(gap_acl_state_t state, unsigned } else if ((reason == 0xb) || (reason > 0x45)) { // 0xb:重复点击连接按钮 0x45:acl状态最大参数 WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "reason is false."); SetTagDisconnectView(false); + } + else if(reason == 0x2){ + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "连接失败,链路连接被对端主动拒绝/未响应 reason is 0x2."); + // 检查是否是期望连接的设备 + BluetoothCaseInfo *expectedDevice = GetTempMacValue(); + bool isExpectedDevice = false; + if (expectedDevice != nullptr) { + isExpectedDevice = (memcmp(expectedDevice->addr, bdAddr.addr, BD_ADDR_LEN) == 0); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "连接失败: 期望设备=%02x%02x%02x%02x%02x%02x, 回调地址=%02x%02x%02x%02x%02x%02x, 匹配=%d", + expectedDevice->addr[5], expectedDevice->addr[4], expectedDevice->addr[3], + expectedDevice->addr[2], expectedDevice->addr[1], expectedDevice->addr[0], + bdAddr.addr[5], bdAddr.addr[4], bdAddr.addr[3], + bdAddr.addr[2], bdAddr.addr[1], bdAddr.addr[0], + isExpectedDevice); + } + // 清除连接状态标记(无论地址是否匹配,都清除,因为连接已失败) + SetTagScanDeviceClicked(false); + // 清空正在连接的设备地址 + (void)memset_s(&remoteConnectAddr, sizeof(bd_addr_t), 0, sizeof(bd_addr_t)); + // 刷新设备列表以停止"连接中"动画 + ThunderBirdBlueView *thunderBirdBlueView = ThunderBirdBlueView::GetInstance(); + if (thunderBirdBlueView != nullptr) { + thunderBirdBlueView->RefreshDeviceList(); + } + if(ThunderBirdMainView::GetInstance()) { + int currentView = ThunderBirdMainView::GetInstance()->GetCurrentView(); + ThunderBirdMainView::GetInstance()->ChangeView(currentView, + THUNDERBIRD_BLUEVIEW, + ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_CONNECT_FAILED); + } + return; } if ((state == GAP_ACL_STATE_CONNECTED) || (state == GAP_ACL_STATE_LE_CONNECTED)) { @@ -1037,9 +1074,25 @@ void GapAclStateChangedCallback(const bd_addr_t *bdAddr, gap_acl_state_t state, WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "addr: %02x%02x%02x%02x%02x%02x", bdAddr->addr[5], bdAddr->addr[4], bdAddr->addr[3], /* mac下标 0 1 2 3 4 5 */ bdAddr->addr[2], bdAddr->addr[1], bdAddr->addr[0]); /* mac下标 0 1 2 3 4 5 */ + + // 检查设备类型 + uint32_t deviceClass = gap_get_device_class(bdAddr); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "GapAclStateChangedCallback: deviceClass=0x%x, (class&0x200)=0x%x", + deviceClass, deviceClass & 0x200); + + // 获取当前期望连接的设备地址 + BluetoothModel* btModel = BluetoothModel::GetInstance(); + BluetoothCaseInfo* expectedDevice = btModel->GetTempMacValue(); + if (expectedDevice != nullptr) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "GapAclStateChangedCallback: 期望连接的设备 addr=%02x%02x%02x%02x%02x%02x", + expectedDevice->addr[5], expectedDevice->addr[4], expectedDevice->addr[3], + expectedDevice->addr[2], expectedDevice->addr[1], expectedDevice->addr[0]); + } + static bd_addr_t gapAclConnectAddr{0}; /* 连接后保存手机地址,手表清除手机配对后查询不到class比较手机地址 */ - if ((gap_get_device_class(bdAddr) & 0x200) != 0 || memcmp(gapAclConnectAddr.addr, bdAddr->addr, BD_ADDR_LEN) == 0) { - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "GapAclStateChangedCallback: Mobile Phone Device"); + if ((deviceClass & 0x200) != 0 || memcmp(gapAclConnectAddr.addr, bdAddr->addr, BD_ADDR_LEN) == 0) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "GapAclStateChangedCallback: Mobile Phone Device (class&0x200=%d, matched=%d)", + (deviceClass & 0x200) != 0, memcmp(gapAclConnectAddr.addr, bdAddr->addr, BD_ADDR_LEN) == 0); if (state == GAP_ACL_STATE_DISCONNECTED) { /* 通知msg_center,ble状态仍用bt状态,此处不区分 */ // MsgCenterSendMsg(BT_DISCONNECTED_TO_MSGCENTER, 0, nullptr, 0); diff --git a/code/sdk/application/wearable/ln/nativeapp/nativeui/bluetooth/src/Ln_Bluetooth_apiC.cpp b/code/sdk/application/wearable/ln/nativeapp/nativeui/bluetooth/src/Ln_Bluetooth_apiC.cpp index 466acbe68..71b104c0c 100644 --- a/code/sdk/application/wearable/ln/nativeapp/nativeui/bluetooth/src/Ln_Bluetooth_apiC.cpp +++ b/code/sdk/application/wearable/ln/nativeapp/nativeui/bluetooth/src/Ln_Bluetooth_apiC.cpp @@ -379,9 +379,6 @@ extern "C" // 检查AVRCP连接状态 if (avrcpInf.avrcp_srv_conn_stat != PROFILE_STATE_CONNECTED) { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ln_bt_earphone_set_volume: AVRCP not connected"); - //尝试连接一次AVRCP服务 - uint32_t ret = avrcp_ct_connect(&avrcpInf.bd_addr); - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ln_bt_earphone_get_volume: connect AVRCP, ret=%d", ret); return -1; } @@ -413,9 +410,6 @@ extern "C" // 检查AVRCP连接状态 if (avrcpInf.avrcp_srv_conn_stat != PROFILE_STATE_CONNECTED) { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ln_bt_earphone_get_volume: AVRCP not connected"); - //尝试连接一次AVRCP服务 - uint32_t ret = avrcp_ct_connect(&avrcpInf.bd_addr); - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ln_bt_earphone_get_volume: connect AVRCP, ret=%d", ret); return -1; } diff --git a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdBlueListAdapter.h b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdBlueListAdapter.h index 121f36e71..a7d9ce35c 100644 --- a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdBlueListAdapter.h +++ b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdBlueListAdapter.h @@ -12,6 +12,7 @@ #include "components/ui_view_group.h" #include "components/ui_label.h" #include "components/ui_image_view.h" +#include "components/ui_image_animator.h" #include "bluetooth/BluetoothModel.h" namespace OHOS { @@ -29,6 +30,7 @@ struct DeviceListItem { DeviceItemType type; BluetoothCaseInfo deviceInfo; bool isSelected; + bool isConnecting; // 是否是“连接中”状态(用于显示右侧 loading 动画) }; // 蓝牙设备列表项视图 @@ -43,6 +45,8 @@ public: void SetSectionHeader(const char* title); // 设置选中状态 void SetSelected(bool selected); + // 设置是否处于“连接中”状态(显示/隐藏右侧 loading 动画) + void SetConnecting(bool connecting); // 获取设备信息 BluetoothCaseInfo* GetDeviceInfo(void); // 检查是否是分组标题 @@ -54,10 +58,12 @@ private: UILabel nameLabel_; // 设备名称标签 UIImageView connectedIcon_; // 已连接图标(小圆点) UIImageView borderImage_; // 选中边框 + UIImageAnimatorView *connectingAnimator_; // 连接中 loading 动画 BluetoothCaseInfo deviceInfo_{}; bool isSelected_{false}; bool isSectionHeader_{false}; bool isConnected_{false}; + bool isConnecting_{false}; }; // 蓝牙设备列表适配器 diff --git a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdBlueView.h b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdBlueView.h index f9c5d2372..40c18ce38 100644 --- a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdBlueView.h +++ b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdBlueView.h @@ -20,14 +20,6 @@ namespace OHOS static constexpr int16_t TB_BLUE_SEARCH_ANIM_FRAMES = 24; static constexpr int16_t TB_BLUE_SEARCH_ANIM_INTERVAL = 33; - // 选择动画配置 - static constexpr int16_t TB_BLUE_SELECT_ANIM_X = 148; - static constexpr int16_t TB_BLUE_SELECT_ANIM_Y = 102; - static constexpr int16_t TB_BLUE_SELECT_ANIM_W = 24; - static constexpr int16_t TB_BLUE_SELECT_ANIM_H = 24; - static constexpr int16_t TB_BLUE_SELECT_ANIM_FRAMES = 49; - static constexpr int16_t TB_BLUE_SELECT_ANIM_INTERVAL = 41; - // 搜索动画图片路径数组 static const char *TB_BLUE_SEARCH_PATHS[TB_BLUE_SEARCH_ANIM_FRAMES] = { TB_SEARCH_IMAGE_1, @@ -56,58 +48,6 @@ namespace OHOS TB_SEARCH_IMAGE_24, }; - // 选择动画图片路径数组(复用搜索动画图片) - static const char *TB_BLUE_SELECT_PATHS[TB_BLUE_SELECT_ANIM_FRAMES] = { - TB_LIST_IMAGE_1, - TB_LIST_IMAGE_2, - TB_LIST_IMAGE_3, - TB_LIST_IMAGE_4, - TB_LIST_IMAGE_5, - TB_LIST_IMAGE_6, - TB_LIST_IMAGE_7, - TB_LIST_IMAGE_8, - TB_LIST_IMAGE_9, - TB_LIST_IMAGE_10, - TB_LIST_IMAGE_11, - TB_LIST_IMAGE_12, - TB_LIST_IMAGE_13, - TB_LIST_IMAGE_14, - TB_LIST_IMAGE_15, - TB_LIST_IMAGE_16, - TB_LIST_IMAGE_17, - TB_LIST_IMAGE_18, - TB_LIST_IMAGE_19, - TB_LIST_IMAGE_20, - TB_LIST_IMAGE_21, - TB_LIST_IMAGE_22, - TB_LIST_IMAGE_23, - TB_LIST_IMAGE_24, - TB_LIST_IMAGE_25, - TB_LIST_IMAGE_26, - TB_LIST_IMAGE_27, - TB_LIST_IMAGE_28, - TB_LIST_IMAGE_29, - TB_LIST_IMAGE_30, - TB_LIST_IMAGE_31, - TB_LIST_IMAGE_32, - TB_LIST_IMAGE_33, - TB_LIST_IMAGE_34, - TB_LIST_IMAGE_35, - TB_LIST_IMAGE_36, - TB_LIST_IMAGE_37, - TB_LIST_IMAGE_38, - TB_LIST_IMAGE_39, - TB_LIST_IMAGE_40, - TB_LIST_IMAGE_41, - TB_LIST_IMAGE_42, - TB_LIST_IMAGE_43, - TB_LIST_IMAGE_44, - TB_LIST_IMAGE_45, - TB_LIST_IMAGE_46, - TB_LIST_IMAGE_47, - TB_LIST_IMAGE_48, - TB_LIST_IMAGE_49, - }; // 前向声明 class ThunderBirdBlueListAdapter; @@ -170,11 +110,8 @@ namespace OHOS // 动画组件 UIImageAnimatorView *searchAnimator{nullptr}; - UIImageAnimatorView *selectAnimator{nullptr}; ImageAnimatorInfo searchImageInfo[TB_BLUE_SEARCH_ANIM_FRAMES]; - ImageAnimatorInfo selectImageInfo[TB_BLUE_SELECT_ANIM_FRAMES]; const char **searchPathsArray{nullptr}; - const char **selectPathsArray{nullptr}; // 设备列表适配器 ThunderBirdBlueListAdapter *deviceListAdapter_{nullptr}; diff --git a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdBlueListAdapter.cpp b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdBlueListAdapter.cpp index 67a863c77..b6ce3c372 100644 --- a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdBlueListAdapter.cpp +++ b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdBlueListAdapter.cpp @@ -7,9 +7,54 @@ #include "thunderbird/include/ThunderBirdBlueListAdapter.h" #include "wearable_log.h" #include "bts_br_gap.h" +#include "UiConfig.h" namespace OHOS { +//======================================== +// 连接中动画资源配置(复用列表动画帧) +//======================================== +namespace { +// 使用前 16 帧列表动画作为“连接中” loading 动画 +constexpr uint8_t TB_BLUE_CONNECT_ANIM_FRAMES = 49; +constexpr uint16_t TB_BLUE_CONNECT_ANIM_INTERVAL = 50; // 每帧 50ms,约 20fps + +static const char *TB_BLUE_CONNECT_PATHS[TB_BLUE_CONNECT_ANIM_FRAMES] = { + TB_LIST_IMAGE_1, TB_LIST_IMAGE_2, TB_LIST_IMAGE_3, TB_LIST_IMAGE_4, + TB_LIST_IMAGE_5, TB_LIST_IMAGE_6, TB_LIST_IMAGE_7, TB_LIST_IMAGE_8, + TB_LIST_IMAGE_9, TB_LIST_IMAGE_10, TB_LIST_IMAGE_11, TB_LIST_IMAGE_12, + TB_LIST_IMAGE_13, TB_LIST_IMAGE_14, TB_LIST_IMAGE_15, TB_LIST_IMAGE_16, + TB_LIST_IMAGE_17, TB_LIST_IMAGE_18, TB_LIST_IMAGE_19, TB_LIST_IMAGE_20, + TB_LIST_IMAGE_21, TB_LIST_IMAGE_22, TB_LIST_IMAGE_23, TB_LIST_IMAGE_24, + TB_LIST_IMAGE_25, TB_LIST_IMAGE_26, TB_LIST_IMAGE_27, TB_LIST_IMAGE_28, + TB_LIST_IMAGE_29, TB_LIST_IMAGE_30, TB_LIST_IMAGE_31, TB_LIST_IMAGE_32, + TB_LIST_IMAGE_33, TB_LIST_IMAGE_34, TB_LIST_IMAGE_35, TB_LIST_IMAGE_36, + TB_LIST_IMAGE_37, TB_LIST_IMAGE_38, TB_LIST_IMAGE_39, TB_LIST_IMAGE_40, + TB_LIST_IMAGE_41, TB_LIST_IMAGE_42, TB_LIST_IMAGE_43, TB_LIST_IMAGE_44, + TB_LIST_IMAGE_45, TB_LIST_IMAGE_46, TB_LIST_IMAGE_47, TB_LIST_IMAGE_48, + TB_LIST_IMAGE_49, +}; + +static ImageAnimatorInfo g_connectAnimInfo[TB_BLUE_CONNECT_ANIM_FRAMES]; +static bool g_connectAnimInited = false; + +static void InitConnectAnimInfo() +{ + if (g_connectAnimInited) { + return; + } + for (uint8_t i = 0; i < TB_BLUE_CONNECT_ANIM_FRAMES; i++) { + g_connectAnimInfo[i].imagePath = TB_BLUE_CONNECT_PATHS[i]; + g_connectAnimInfo[i].imageType = IMG_SRC_FILE_PATH; + g_connectAnimInfo[i].pos.x = 0; + g_connectAnimInfo[i].pos.y = 0; + g_connectAnimInfo[i].width = 24; + g_connectAnimInfo[i].height = 24; + } + g_connectAnimInited = true; +} +} // namespace + // 列表项尺寸常量 constexpr uint16_t ITEM_WIDTH = 240; constexpr uint16_t ITEM_HEIGHT = 40; @@ -21,9 +66,8 @@ constexpr uint16_t SECTION_FONT_SIZE = 14; // 颜色定义 constexpr int64_t COLOR_ITEM_BG = 0xFFAD590B; // 设备项背景色(深灰) -constexpr int64_t COLOR_BORDER_SELECTED = 0xFFED6C00; // 选中边框颜色(橙色) +constexpr int64_t COLOR_BORDER_SELECTED = 0xFFAD590B; // 选中边框颜色(橙色) constexpr int64_t COLOR_TEXT_WHITE = 0xFFFFFFFF; // 白色文字 -constexpr int64_t COLOR_TEXT_GRAY = 0xFFCCCCCC; // 灰色文字(分组标题) constexpr int64_t COLOR_CONNECTED_DOT = 0xFF4FC34C; // 已连接指示点颜色(绿色) //======================================== @@ -44,6 +88,13 @@ ThunderBirdBlueDeviceItemView::~ThunderBirdBlueDeviceItemView() Remove(&borderImage_); Remove(&nameLabel_); Remove(&connectedIcon_); + Remove(connectingAnimator_); + if(connectingAnimator_) + { + connectingAnimator_->Stop(); + delete connectingAnimator_; + connectingAnimator_ = nullptr; + } } void ThunderBirdBlueDeviceItemView::SetupChildViews() @@ -51,7 +102,7 @@ void ThunderBirdBlueDeviceItemView::SetupChildViews() WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "SetupChildViews"); borderImage_.SetPosition(0, 0, ITEM_WIDTH, ITEM_HEIGHT); - borderImage_.SetStyle(STYLE_BACKGROUND_COLOR, COLOR_TEXT_GRAY); + borderImage_.SetStyle(STYLE_BACKGROUND_COLOR, COLOR_BORDER_SELECTED); borderImage_.SetStyle(STYLE_BACKGROUND_OPA, OPA_OPAQUE); borderImage_.SetStyle(STYLE_BORDER_RADIUS, 10); borderImage_.SetVisible(false); @@ -70,12 +121,40 @@ void ThunderBirdBlueDeviceItemView::SetupChildViews() connectedIcon_.SetStyle(STYLE_BORDER_RADIUS, CONNECTED_ICON_SIZE / 2); connectedIcon_.SetVisible(false); Add(&connectedIcon_); + + // “连接中” loading 动画(在已连接小圆点左侧) + InitConnectAnimInfo(); + int16_t animX = ITEM_WIDTH - 40; + int16_t animY = (ITEM_HEIGHT - 24) / 2; + printf("animX=%d animY=%d\n", animX, animY); + connectingAnimator_ = new UIImageAnimatorView(); + if(!connectingAnimator_) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "connectingAnimator_ create failed"); + return; + } + connectingAnimator_->SetPosition(animX, animY, 24, 24); + connectingAnimator_->SetStyle(STYLE_BACKGROUND_COLOR, 0xffffffff); + connectingAnimator_->SetStyle(STYLE_BACKGROUND_OPA, 0x00); + // 更新帧位置 + for (uint8_t i = 0; i < TB_BLUE_CONNECT_ANIM_FRAMES; i++) { + g_connectAnimInfo[i].pos.x = animX; + g_connectAnimInfo[i].pos.y = animY; + g_connectAnimInfo[i].width = 24; + g_connectAnimInfo[i].height = 24; + } + connectingAnimator_->SetImageAnimatorSrc(g_connectAnimInfo, TB_BLUE_CONNECT_ANIM_FRAMES, TB_BLUE_CONNECT_ANIM_INTERVAL); + connectingAnimator_->SetRepeat(true); + connectingAnimator_->SetAutoEnable(false); + connectingAnimator_->SetResizeMode(UIImageView::FILL); + connectingAnimator_->SetVisible(false); + Add(connectingAnimator_); } // 设置设备信息(包括分组标题) void ThunderBirdBlueDeviceItemView::SetDeviceInfo(const BluetoothCaseInfo& info, bool isConnected) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SetDeviceInfo name=%s isConnected=%d", + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "SetDeviceInfo name=%s isConnected=%d", info.deviceName, isConnected); isSectionHeader_ = false; @@ -91,6 +170,8 @@ void ThunderBirdBlueDeviceItemView::SetDeviceInfo(const BluetoothCaseInfo& info, // 显示/隐藏已连接指示 connectedIcon_.SetVisible(isConnected); + + // “连接中”动画状态由 SetConnecting 控制,这里不做处理 Invalidate(); } @@ -102,6 +183,7 @@ void ThunderBirdBlueDeviceItemView::SetSectionHeader(const char* title) isSectionHeader_ = true; isConnected_ = false; + isConnecting_ = false; // 设置标题文字 nameLabel_.SetText(title); @@ -109,14 +191,39 @@ void ThunderBirdBlueDeviceItemView::SetSectionHeader(const char* title) nameLabel_.SetPosition(20, 0, 200, ITEM_HEIGHT); nameLabel_.SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_BOTTOM,UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER); - // 隐藏已连接指示 + // 隐藏已连接指示与加载动画 connectedIcon_.SetVisible(false); + connectingAnimator_->SetVisible(false); + connectingAnimator_->Stop(); borderImage_.SetVisible(false); Invalidate(); } +// 设置是否处于“连接中”状态(显示/隐藏右侧 loading 动画) +void ThunderBirdBlueDeviceItemView::SetConnecting(bool connecting) +{ + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "SetConnecting=%d isSectionHeader=%d", connecting, isSectionHeader_); + isConnecting_ = connecting; + + if (isSectionHeader_) { + connectingAnimator_->SetVisible(false); + connectingAnimator_->Stop(); + return; + } + + if (connecting) { + connectingAnimator_->SetVisible(true); + connectingAnimator_->Start(); + } else { + connectingAnimator_->SetVisible(false); + connectingAnimator_->Stop(); + } + + Invalidate(); +} + void ThunderBirdBlueDeviceItemView::SetSelected(bool selected) { WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "SetSelected=%d isSectionHeader=%d", selected, isSectionHeader_); @@ -218,7 +325,11 @@ void ThunderBirdBlueListAdapter::BuildDisplayList() node = node->next_; } - // 第二步:优先添加已连接的设备 + // 获取当前正在尝试连接的设备(用于判断“连接中”状态) + bool hasClick = btModel->IsTagScanDeviceClicked(); + BluetoothCaseInfo* connectingInfo = hasClick ? btModel->GetTempMacValue() : nullptr; + + // 第二步:优先添加已连接的设备(已连接的不显示 loading) for (auto& device : connectedDevicesList) { if (connectedCount >= MAX_CONNECTED_DEVICES) { break; @@ -227,12 +338,13 @@ void ThunderBirdBlueListAdapter::BuildDisplayList() item.type = DeviceItemType::DEVICE_CONNECTED; item.deviceInfo = device; item.isSelected = false; + item.isConnecting = false; displayList_.push_back(item); connectedCount++; WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Added my device (connected): %s", device.deviceName); } - // 第三步:再添加未连接的设备(如果还有空间) + // 第三步:再添加未连接的设备(如果还有空间),若为当前点击目标且未连接,则标记为“连接中” for (auto& device : unconnectedDevicesList) { if (connectedCount >= MAX_CONNECTED_DEVICES) { break; @@ -241,9 +353,17 @@ void ThunderBirdBlueListAdapter::BuildDisplayList() item.type = DeviceItemType::DEVICE_CONNECTED; item.deviceInfo = device; item.isSelected = false; + bool isConnecting = false; + if (hasClick && connectingInfo != nullptr && + (memcmp(connectingInfo->addr, device.addr, BD_ADDR_LEN) == 0) && + !bt_is_acl_connected(reinterpret_cast(device.addr))) { + isConnecting = true; + } + item.isConnecting = isConnecting; displayList_.push_back(item); connectedCount++; - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Added my device (unconnected): %s", device.deviceName); + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Added my device (unconnected, connecting=%d): %s", + isConnecting, device.deviceName); } } @@ -274,9 +394,19 @@ void ThunderBirdBlueListAdapter::BuildDisplayList() item.type = DeviceItemType::DEVICE_NEARBY; item.deviceInfo = device; item.isSelected = false; + // 判断是否为当前正在发起连接的设备(用于显示“连接中”动画) + bool hasClick = btModel->IsTagScanDeviceClicked(); + BluetoothCaseInfo* connectingInfo = hasClick ? btModel->GetTempMacValue() : nullptr; + bool isConnecting = false; + if (hasClick && connectingInfo != nullptr && + (memcmp(connectingInfo->addr, device.addr, BD_ADDR_LEN) == 0)) { + isConnecting = true; + } + item.isConnecting = isConnecting; displayList_.push_back(item); nearbyCount++; - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Added nearby device: %s", device.deviceName); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Added nearby device: %s, connecting=%d", + device.deviceName, isConnecting); } WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "BuildDisplayList done: connected=%d, nearby=%d, total=%d", @@ -323,22 +453,28 @@ UIView* ThunderBirdBlueListAdapter::GetView(UIView* inView, int16_t index) case DeviceItemType::SECTION_HEADER_CONNECTED: WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Setting SECTION_HEADER_CONNECTED"); item->SetSectionHeader("我的设备"); + item->SetConnecting(false); break; case DeviceItemType::SECTION_HEADER_NEARBY: WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Setting SECTION_HEADER_NEARBY"); item->SetSectionHeader("附近的设备"); + item->SetConnecting(false); break; case DeviceItemType::DEVICE_CONNECTED: { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Setting DEVICE_CONNECTED: %s", it->deviceInfo.deviceName); // 仅对当前实际已连接的设备显示橙色小圆点 bool isConnectedNow = bt_is_acl_connected(reinterpret_cast(it->deviceInfo.addr)); item->SetDeviceInfo(it->deviceInfo, isConnectedNow); + // “连接中”动画:仅对未连接但标记为 isConnecting 的设备显示 + bool showConnecting = (!isConnectedNow) && it->isConnecting; + item->SetConnecting(showConnecting); item->SetSelected(index == selectedIndex_); break; } case DeviceItemType::DEVICE_NEARBY: WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Setting DEVICE_NEARBY: %s", it->deviceInfo.deviceName); item->SetDeviceInfo(it->deviceInfo, false); + item->SetConnecting(it->isConnecting); item->SetSelected(index == selectedIndex_); break; default: diff --git a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdBlueView.cpp b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdBlueView.cpp index 7663c610f..9350f483b 100644 --- a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdBlueView.cpp +++ b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdBlueView.cpp @@ -51,7 +51,6 @@ namespace OHOS if (DeviceList != nullptr) { delete DeviceList; DeviceList = nullptr; } if (deviceListAdapter_ != nullptr) { delete deviceListAdapter_; deviceListAdapter_ = nullptr; } if (searchAnimator != nullptr) { delete searchAnimator; searchAnimator = nullptr; } - if (selectAnimator != nullptr) { delete selectAnimator; selectAnimator = nullptr; } } bool ThunderBirdBlueView::EnsureNetAnimator() @@ -95,41 +94,6 @@ namespace OHOS return true; } - bool ThunderBirdBlueView::EnsureSelectAnimator() - { - if (selectAnimator == nullptr) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdBlueView::EnsureSelectAnimator: 创建选择动画"); - selectPathsArray = TB_BLUE_SELECT_PATHS; - selectAnimator = new UIImageAnimatorView(); - if (selectAnimator == nullptr) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdBlueView new UIImageAnimatorView fail"); - return false; - } - selectAnimator->SetAutoEnable(false); - for (uint8_t i = 0; i < TB_BLUE_SELECT_ANIM_FRAMES; i++) - { - selectImageInfo[i].imagePath = (selectPathsArray[i]); - selectImageInfo[i].imageType = IMG_SRC_FILE_PATH; - selectImageInfo[i].pos.x = TB_BLUE_SELECT_ANIM_X; - selectImageInfo[i].pos.y = TB_BLUE_SELECT_ANIM_Y; - selectImageInfo[i].width = TB_BLUE_SELECT_ANIM_W; - selectImageInfo[i].height = TB_BLUE_SELECT_ANIM_H; - } - selectAnimator->SetPosition(TB_BLUE_SELECT_ANIM_X, TB_BLUE_SELECT_ANIM_Y, TB_BLUE_SELECT_ANIM_W, TB_BLUE_SELECT_ANIM_H); - selectAnimator->SetStyle(STYLE_BACKGROUND_COLOR, 0xffffffff); - selectAnimator->SetStyle(STYLE_BACKGROUND_OPA, 0x00); - selectAnimator->SetImageAnimatorSrc(selectImageInfo, TB_BLUE_SELECT_ANIM_FRAMES, TB_BLUE_SELECT_ANIM_INTERVAL); - selectAnimator->SetRepeat(true); - selectAnimator->SetRepeatTimes(1); - selectAnimator->SetResizeMode(UIImageView::COVER); - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdBlueView::EnsureSelectAnimator: 动画配置完成,位置=(%d,%d), 大小=(%d,%d), 帧数=%d", - TB_BLUE_SELECT_ANIM_X, TB_BLUE_SELECT_ANIM_Y, TB_BLUE_SELECT_ANIM_W, TB_BLUE_SELECT_ANIM_H, TB_BLUE_SELECT_ANIM_FRAMES); - } - return true; - } - void ThunderBirdBlueView::InitDeviceListAdapter(void) { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdBlueView::InitDeviceListAdapter"); @@ -261,12 +225,7 @@ namespace OHOS { return nullptr; } - if(!EnsureSelectAnimator()) - { - return nullptr; - } group->Add(searchAnimator); - group->Add(selectAnimator); // 初始化设备列表适配器 InitDeviceListAdapter(); @@ -291,7 +250,6 @@ namespace OHOS if (RemindIcon4) { RemindIcon4->SetVisible(false); } if (DeviceList) { DeviceList->SetVisible(false); } if (searchAnimator) { searchAnimator->SetVisible(false); searchAnimator->Stop(); } - if (selectAnimator) { selectAnimator->SetVisible(false); selectAnimator->Stop(); } switch (showView) { @@ -461,13 +419,6 @@ namespace OHOS searchAnimator->Stop(); } - // 显示选择动画 - if (selectAnimator) - { - // selectAnimator->SetVisible(true); - // selectAnimator->Start(); - } - // 不显示标题(列表中已有分组标题) if (TextLabel) { @@ -845,8 +796,14 @@ namespace OHOS return; } - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "OnKeyConfirm: connecting to %s", - selectedDevice->deviceName); + WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "OnKeyConfirm: connecting to %s,addr:%02x%02x%02x%02x%02x%02x", + selectedDevice->deviceName, + selectedDevice->addr[5], + selectedDevice->addr[4], + selectedDevice->addr[3], + selectedDevice->addr[2], + selectedDevice->addr[1], + selectedDevice->addr[0]); // 设置临时MAC值并发起连接 BluetoothModel::GetInstance()->SetTempMacValue(selectedDevice); @@ -873,20 +830,12 @@ namespace OHOS BluetoothModel::GetInstance()->DisconnectRemoteDevice(); BluetoothModel::GetInstance()->SetTagConnectNew(true); } + + RefreshDeviceList(); + // 发起连接 - int ret = BluetoothModel::GetInstance()->ConnectRemoteDevice( - (const bd_addr_t*)&selectedDevice->addr); - - if (ret != true) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ConnectRemoteDevice failed: %d", ret); - // 可以在这里显示连接失败提示 - if(ThunderBirdMainView::GetInstance()) { - int currentView = ThunderBirdMainView::GetInstance()->GetCurrentView(); - ThunderBirdMainView::GetInstance()->ChangeView(currentView, - THUNDERBIRD_BLUEVIEW, - ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_CONNECT_FAILED); - } - } + BluetoothModel::GetInstance()->ConnectRemoteDevice((const bd_addr_t*)&selectedDevice->addr); + return; } // 处理连接失败操作:重新发送连接操作 @@ -908,9 +857,16 @@ namespace OHOS WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "GetTempMacValue failed"); return; } + BluetoothModel::GetInstance()->SetTagScanDeviceClicked(true); - WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "OnKeyConfirm: connecting to %s", - caseInfo->deviceName); + WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "OnKeyConfirm: connecting to %s,addr:%02x%02x%02x%02x%02x%02x", + caseInfo->deviceName, + caseInfo->addr[5], + caseInfo->addr[4], + caseInfo->addr[3], + caseInfo->addr[2], + caseInfo->addr[1], + caseInfo->addr[0]); // 判断是否已有连接 bd_addr_t *lastAddr = BluetoothModel::GetInstance()->GetLastConnedAddr(); @@ -923,20 +879,11 @@ namespace OHOS BluetoothModel::GetInstance()->SetTagConnectNew(true); } + RefreshDeviceList(); + // 发起连接 - int ret = BluetoothModel::GetInstance()->ConnectRemoteDevice( - (const bd_addr_t*)&caseInfo->addr); - - if (ret != true) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ConnectRemoteDevice failed: %d", ret); - // 可以在这里显示连接失败提示 - if(ThunderBirdMainView::GetInstance()) { - int currentView = ThunderBirdMainView::GetInstance()->GetCurrentView(); - ThunderBirdMainView::GetInstance()->ChangeView(currentView, - THUNDERBIRD_BLUEVIEW, - ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_CONNECT_FAILED); - } - } + BluetoothModel::GetInstance()->ConnectRemoteDevice((const bd_addr_t*)&caseInfo->addr); + return; } // 获取当前选中的设备索引 diff --git a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdModel.cpp b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdModel.cpp index 7c1013ff2..bdce4603a 100644 --- a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdModel.cpp +++ b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdModel.cpp @@ -2874,10 +2874,30 @@ extern "C" { void ThunderBirdModel::HandleBluetoothEarphoneConnectStatus(int connectStatus) { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleBluetoothEarphoneConnectStatus: 收到蓝牙耳机连接状态通知,connectStatus=%d", connectStatus); - if(ThunderBirdMainView::GetInstance()){ - int currentView = ThunderBirdMainView::GetInstance()->GetCurrentView(); //获取当前视图 - ThunderBirdMainView::GetInstance()->earphoneIcon->SetVisible(connectStatus); - // ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_BLUEVIEW, ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_EXIT); + ThunderBirdMainView *mainView = ThunderBirdMainView::GetInstance(); + if (mainView == nullptr) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "HandleBluetoothEarphoneConnectStatus: mainView nullptr"); + return; + } + + int currentView = mainView->GetCurrentView(); // 获取当前视图 + // 更新耳机图标 + if (mainView->earphoneIcon != nullptr) { + mainView->earphoneIcon->SetVisible(connectStatus != 0); + } + + // 连接完成/失败后,停止列表中的“连接中”动画 + // 逻辑:无论成功(1)还是失败(0),都认为一次连接流程结束,清除“正在连接”标志并刷新列表 + BluetoothModel::GetInstance()->SetTagScanDeviceClicked(false); + + if (currentView == THUNDERBIRD_BLUEVIEW) { + ThunderBirdBlueView *blueView = ThunderBirdBlueView::GetInstance(); + if (blueView != nullptr) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "HandleBluetoothEarphoneConnectStatus: refresh blue list, connectStatus=%d", + connectStatus); + blueView->RefreshDeviceList(); + } } } diff --git a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdPresenter.cpp b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdPresenter.cpp index 407675643..028a4450d 100644 --- a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdPresenter.cpp +++ b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdPresenter.cpp @@ -890,6 +890,7 @@ namespace OHOS case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DISCONNECT_SUCCESS: //重新发送连接操作 ThunderBirdBlueView::GetInstance()->OnConnectFailed(); + ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_BLUEVIEW, ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DEVICE_LIST); break; case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DEVICE_LIST: // ThunderBirdBlueView::GetInstance()->OnKeyUp();// 音量+键:选择上一个设备 @@ -899,6 +900,7 @@ namespace OHOS case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_CONNECT_FAILED: //重新发送连接操作 ThunderBirdBlueView::GetInstance()->OnConnectFailed(); + ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_BLUEVIEW, ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DEVICE_LIST); break; } } -- 2.17.1