Browse Source

优化了一些代码的实现

MoYuWang 9 months ago
parent
commit
86d78f43b5

+ 127 - 0
Classes/IAP/Shop/IAPCardView.cpp

@@ -0,0 +1,127 @@
+//
+//  IAPCardView.cpp
+//  demo
+//
+//  Created by Red_mini on 2024/10/25.
+//
+
+#include "IAPCardView.hpp"
+
+
+void IAPCardView::setDelegate(IAPCardViewDelegate *delegate){
+    if(delegate){
+        _delegate = delegate;
+    }
+}
+
+IAPCardView* IAPCardView::create(cocos2d::Size &viewSize, sDotCfg &dotCfg){
+    // 创建 PageView 用于分页滑动卡片
+    IAPCardView* ret = new IAPCardView();
+    if (ret && ret->_init(viewSize, dotCfg)) {
+        ret->autorelease();
+        return ret;
+    } else {
+        delete ret;
+        return nullptr;
+    }
+    
+}
+
+void IAPCardView::addCard(Node* card){
+    if(card == nullptr) return;
+    
+    auto layout = ui::Layout::create();
+    layout->setContentSize(_pageView->getContentSize());
+
+    // 将卡片添加到布局并居中
+    card->setPosition(Vec2(layout->getContentSize().width / 2, layout->getContentSize().height / 2));
+    layout->addChild(card);
+    // 添加到 PageView
+    _pageView->addPage(layout);
+
+    // 添加指示点
+    float spacing = _dotCfg.sepWidth;
+    auto newDot = Sprite::create(_dotCfg.normalSp);
+    newDot->setPosition(Vec2(_indicators.size() * spacing, _dotCfg.yStart));
+    _indicators.push_back(newDot);
+    // 指示点添加到父节点中
+    _indicatorNode->addChild(newDot);
+    
+    // 如果该卡片是添加的第一个
+    if(_indicators.size() == 1){
+        auto indicator = dynamic_cast<Sprite*>(_indicators[0]);
+        if(indicator){
+            indicator->setTexture(_dotCfg.hightSp); // 切换为选中图片
+        }
+    }
+    // 调整指示点位置
+    float indicatorNodeWidth = (_indicators.size() - 1) * spacing;
+    _indicatorNode->setPosition(Vec2(_pageView->getContentSize().width / 2 - indicatorNodeWidth / 2, _dotCfg.yStart)); // 调整y轴位置
+}
+
+void IAPCardView::removeCard(int index){
+    // 确保索引合法
+    if (index < 0 || index >= _pageView->getPages().size()) {
+        CCLOG("Invalid index: %d", index);
+        return;
+    }
+    
+    // 从 PageView 中移除指定页面
+    _pageView->removePageAtIndex(index);
+    
+    // 从指示点数组中移除指定指示点,并从父节点中删除
+    if (index < _indicators.size()) {
+        auto indicator = _indicators[index];
+        _indicatorNode->removeChild(indicator);
+        _indicators.erase(_indicators.begin() + index);
+    }
+
+    // 更新剩余指示点的位置
+    float spacing = _dotCfg.sepWidth;
+    for (int i = 0; i < _indicators.size(); ++i) {
+        _indicators[i]->setPosition(Vec2(i * spacing, _dotCfg.yStart));
+    }
+    
+}
+
+bool IAPCardView::_init(Size &viewSize, sDotCfg &dotCfg){
+    _viewSize = viewSize;
+    _dotCfg = dotCfg;
+    
+    // 创建 PageView 用于分页滑动卡片
+    _pageView = ui::PageView::create();
+    _pageView->setContentSize(viewSize);
+    // 创建总指示器Node
+    _indicatorNode = Node::create();
+    
+    // 设置 PageView 的分页切换效果(滑动自动切换)
+    _pageView->setUsingCustomScrollThreshold(true);  // 启用自定义滑动阈值
+    _pageView->setCustomScrollThreshold(50);         // 设置触发翻页的滑动距离阈值
+    _pageView->setAutoScrollStopEpsilon(0.05f);      // 提高自动滚动停止的精度
+    
+    this->addChild(_pageView);
+    this->addChild(_indicatorNode);
+    
+    
+    // 添加回调函数监听pageView变化
+    _pageView->addEventListener([&](Ref* sender, ui::PageView::EventType type) {
+        auto pageView = dynamic_cast<ui::PageView*>(sender);
+        int currentPageIndex = pageView->getCurrentPageIndex();
+        
+        // 更新指示点的图片,当前页的指示点变为选中状态,其他保持未选中
+        for (int i = 0; i < _indicators.size(); i++) {
+            auto indicator = dynamic_cast<Sprite*>(_indicators[i]);
+            if (i == currentPageIndex) {
+                indicator->setTexture(_dotCfg.hightSp); // 切换为选中图片
+            } else {
+                indicator->setTexture(_dotCfg.normalSp); // 切换为未选中图片
+            }
+        }
+        // 如果delegate存在通知delegate卡片页数改变
+        if(_delegate){
+            _delegate->onCardChanged(currentPageIndex);
+        }
+    });
+    
+    return true;
+}

+ 65 - 0
Classes/IAP/Shop/IAPCardView.hpp

@@ -0,0 +1,65 @@
+//
+//  IAPCardView.hpp
+//  demo
+//
+//  Created by Red_mini on 2024/10/25.
+//
+
+#ifndef IAPCardView_hpp
+#define IAPCardView_hpp
+
+#include "ui/UIPageView.h"
+#include "cocos2d.h"
+
+/**
+    IAPCardView 类 :
+        封装一个左右滑动切换页面的View,每个页面是一个Node,且带有页面总数及当前页面显示圆点
+        
+        1. sDotCfg为iPhone主屏下方小圆圈配置。定义如下:
+          struct sDotCfg {
+              int sepWidth = 0;            //每个小圆圈之间的间距
+              int yStart = 0;                //默认是在viewSize的底部.也可以设置偏移.
+              string highSp = "";            //当前页高亮与普通对应的图片.
+              string normalSp = "";
+          };
+ 
+ */
+
+class IAPCardView;
+class IAPCardViewDelegate{
+public:
+    virtual void onCardChanged(int currentPageIndex) = 0; // 页面切换时调用
+};
+
+class IAPCardView : public Layer{
+public:
+    struct sDotCfg{
+        int sepWidth = 0;
+        int yStart = 0;
+        string hightSp = "";
+        string normalSp = "";
+    };
+    
+    static IAPCardView* create(cocos2d::Size& viewSize, sDotCfg& dotCfg);
+    
+    void setDelegate(IAPCardViewDelegate* delegate);
+    
+    void addCard(Node* card);
+    
+    void removeCard(int index);
+    
+private:
+    // 初始化函数
+    bool _init(Size& viewSize, sDotCfg& dotCfg);
+    
+private:
+    IAPCardViewDelegate* _delegate = nullptr;  // 委托对象
+    
+    sDotCfg _dotCfg;
+    Size _viewSize;
+    ui::PageView* _pageView = nullptr;
+    Node* _indicatorNode = nullptr;
+    std::vector<Sprite*> _indicators;
+};
+
+#endif /* IAPCardView_hpp */

+ 17 - 66
Classes/IAP/Shop/IAPCtlShopUI.cpp

@@ -17,6 +17,10 @@
 #include "IAPCtlShopItem.hpp"
 #include "IAPDefine.hpp"
 #include "IAPTestCard.hpp"
+
+#include "IAPCardView.hpp"
+#include "IAPTestCardViewDelegate.hpp"
+
 #include <regex>
 
 IAPCtlShopUI* IAPCtlShopUI::_instance = nullptr;
@@ -148,13 +152,6 @@ void IAPCtlShopUI::showPlacementsInNode(cocos2d::Node *pNode, const vector<std::
         }
     };
     
-    // 防止拉动的时候才创建
-    _layer->scheduleOnce([=](float){
-        for (int i=0; i<_allSizes.size(); i++) {
-            _tableView->updateCellAtIndex(i);
-        }
-    }, 0.05, "SCH_Update_Cells");
-    
     
     _tableView = redutils::RUTableView::create(&_tableData, cocos2d::Size(size.width, size.height));
     _tableView->setCascadeOpacityEnabled(true);
@@ -173,8 +170,8 @@ bool IAPCtlShopUI::addAPlacement(const iap::IAPPlacement &plInfo){
     
     _placements[plInfo.id] = plInfo;
     
-    std::vector<DrawNode*> drawNode;
-    _indicators[plInfo.id] = drawNode;
+    std::vector<Node*> nodeVec;
+    _indicators[plInfo.id] = nodeVec;
     
     return true;
 }
@@ -446,70 +443,24 @@ void IAPCtlShopUI::constructShopItem(bool bShowAll) {
 Node* IAPCtlShopUI::createPlacementUI(const iap::IAPPlacement& placement){
     Node* node = Node::create();
     
-    // 创建 PageView 用于分页滑动卡片
-    auto pageView = ui::PageView::create();
-    pageView->setContentSize(cocos2d::Size(584, 250));
+    IAPCardView::sDotCfg cfg;
+    cfg.hightSp = "内购版位_通用_图标_滑动点_已选中.png";
+    cfg.normalSp = "内购版位_通用_图标_滑动点_未选中.png";
+    cfg.sepWidth = 30.0f;
+    cfg.yStart = 0;
+    cocos2d::Size sz = cocos2d::Size(584, 250);
+    IAPCardView* cardView = IAPCardView::create(sz, cfg);
     
-    // 创建指示点的父节点
-    auto indicatorNode = Node::create();
-    float spacing = 20.0f; // 每个指示点之间的间距
+    IAPTestCardViewDelegate* cardViewDelegate = new IAPTestCardViewDelegate();
+    cardView->setDelegate(cardViewDelegate);
     
     // 遍历 placement 中的卡片,依次创建并添加到 PageView 中
     for (int i = 0; i < placement.cards.size(); i++) {
-        // 创建每张卡片的布局容器(PageView 只能添加 Layout 类型的子节点)
-        auto layout = ui::Layout::create();
-        layout->setContentSize(cocos2d::Size(584, 250));
-        
-        auto card = placement.cards[i]->create();  // 假设 card 有 create 方法
-        
-        // 设置卡片的居中位置
-        card->setPosition(Vec2(layout->getContentSize().width / 2, layout->getContentSize().height / 2));
-        layout->addChild(card);
-        
-        // 将布局容器添加到 PageView 中
-        pageView->addPage(layout);
-        
-        // 创建指示点
-        auto indicator = DrawNode::create();
-        Vec2 center(i * spacing, 0); // 水平排列指示点
-        _indicators[placement.id].push_back(indicator);
-        
-        // 画白色圆点
-        indicator->drawDot(center, 5, Color4F(1, 1, 1, 1)); // 白色指示点
-        indicatorNode->addChild(indicator);
+        cardView->addCard(placement.cards[i]->create());
     }
-    
-    // 设置 PageView 的分页切换效果(滑动自动切换)
-    pageView->setUsingCustomScrollThreshold(true);  // 启用自定义滑动阈值
-    pageView->setCustomScrollThreshold(50);        // 设置触发翻页的滑动距离阈值
-    pageView->setAutoScrollStopEpsilon(0.05f); // 提高自动滚动停止的精度
-    
-    // 设置指示点的位置,居中显示在卡片下方
-    float indicatorNodeWidth = (placement.cards.size() - 1) * spacing;
-    indicatorNode->setPosition(Vec2(pageView->getContentSize().width / 2 - indicatorNodeWidth / 2, 0)); // 调整y轴位置
-    node->addChild(indicatorNode);  // 将指示点容器添加到主节点中
-
-    // 添加回调函数监听页面变化
-    pageView->addEventListener([=](Ref* sender, ui::PageView::EventType type) {
-        if (type == ui::PageView::EventType::TURNING) {
-            log("滑动");
-            auto pageView = dynamic_cast<ui::PageView*>(sender);
-            int currentPageIndex = pageView->getCurrentPageIndex();
-            
-            // 更新指示点颜色,当前页的指示点变为红色,其他保持白色
-            for (int i = 0; i < _indicators[placement.id].size(); i++) {
-                _indicators[placement.id][i]->clear(); // 清除之前的绘制
-                Color4F color = (i == currentPageIndex) ? Color4F(1, 0, 0, 1) : Color4F(1, 1, 1, 1); // 红色或白色
-                _indicators[placement.id][i]->drawDot(Vec2(i * 20, 0), 5, color); // 更新指示点颜色
-            }
-        }
-    });
-    
-    // 默认将第一页的指示点设为红色
-    _indicators[placement.id][0]->drawDot(Vec2(0, 0), 5, Color4F(1, 0, 0, 1)); // 当前页红点
 
     // 将 PageView 添加到父节点 node 中
-    node->addChild(pageView);
+    node->addChild(cardView);
         
     return node;
 }

+ 1 - 1
Classes/IAP/Shop/IAPCtlShopUI.hpp

@@ -92,7 +92,7 @@ private:
     int _placementId = 0;
     
     std::map<std::string, iap::IAPPlacement> _placements;
-    std::map<std::string, std::vector<DrawNode*> > _indicators;
+    std::map<std::string, std::vector<Node*> > _indicators;
 };
 
 #endif /* IAPCtlShopUI_hpp */

+ 17 - 0
Classes/IAP/Shop/IAPTestCardViewDelegate.cpp

@@ -0,0 +1,17 @@
+//
+//  IAPTestCardViewDelegate.cpp
+//  demo
+//
+//  Created by Red_mini on 2024/10/25.
+//
+
+#include "IAPTestCardViewDelegate.hpp"
+#include "cocos2d.h"
+
+IAPTestCardViewDelegate::IAPTestCardViewDelegate(){
+    
+}
+
+void IAPTestCardViewDelegate::onCardChanged(int currentPageIndex){
+    log("页面切换到第%d页",currentPageIndex + 1);
+}

+ 23 - 0
Classes/IAP/Shop/IAPTestCardViewDelegate.hpp

@@ -0,0 +1,23 @@
+//
+//  IAPTestCardViewDelegate.hpp
+//  demo
+//
+//  Created by Red_mini on 2024/10/25.
+//
+
+#ifndef IAPTestCardViewDelegate_hpp
+#define IAPTestCardViewDelegate_hpp
+
+#include <stdio.h>
+#include "IAPCardView.hpp"
+
+
+class IAPTestCardViewDelegate : public IAPCardViewDelegate
+{
+public:
+    virtual void onCardChanged(int currentPageIndex) override;
+    
+    IAPTestCardViewDelegate();
+};
+
+#endif /* IAPTestCardViewDelegate_hpp */

+ 16 - 0
proj.ios_mac/demo.xcodeproj/project.pbxproj

@@ -55,6 +55,10 @@
 		C17946182CC7502600779B63 /* IAPTestCard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C17946152CC7502600779B63 /* IAPTestCard.cpp */; };
 		C17ACCBC2CB903BA0072A711 /* TestScene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C17ACCBB2CB903BA0072A711 /* TestScene.cpp */; };
 		C17ACCBD2CB903BA0072A711 /* TestScene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C17ACCBB2CB903BA0072A711 /* TestScene.cpp */; };
+		C18082282CCB3338009DE140 /* IAPCardView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C18082262CCB3338009DE140 /* IAPCardView.cpp */; };
+		C18082292CCB3338009DE140 /* IAPCardView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C18082262CCB3338009DE140 /* IAPCardView.cpp */; };
+		C18082332CCB71D3009DE140 /* IAPTestCardViewDelegate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C18082312CCB71D3009DE140 /* IAPTestCardViewDelegate.cpp */; };
+		C18082342CCB71D3009DE140 /* IAPTestCardViewDelegate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C18082312CCB71D3009DE140 /* IAPTestCardViewDelegate.cpp */; };
 		D44C620C132DFF330009C878 /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D44C620B132DFF330009C878 /* OpenAL.framework */; };
 		D44C620E132DFF430009C878 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D44C620D132DFF430009C878 /* AVFoundation.framework */; };
 		D44C6210132DFF4E0009C878 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D44C620F132DFF4E0009C878 /* AudioToolbox.framework */; };
@@ -196,6 +200,10 @@
 		C17946162CC7502600779B63 /* IAPTestCard.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = IAPTestCard.hpp; sourceTree = "<group>"; };
 		C17ACCBB2CB903BA0072A711 /* TestScene.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TestScene.cpp; sourceTree = "<group>"; };
 		C17ACCC52CB904460072A711 /* TestScene.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestScene.h; sourceTree = "<group>"; };
+		C18082262CCB3338009DE140 /* IAPCardView.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = IAPCardView.cpp; sourceTree = "<group>"; };
+		C18082272CCB3338009DE140 /* IAPCardView.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = IAPCardView.hpp; sourceTree = "<group>"; };
+		C18082312CCB71D3009DE140 /* IAPTestCardViewDelegate.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = IAPTestCardViewDelegate.cpp; sourceTree = "<group>"; };
+		C18082322CCB71D3009DE140 /* IAPTestCardViewDelegate.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = IAPTestCardViewDelegate.hpp; sourceTree = "<group>"; };
 		D44C620B132DFF330009C878 /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = System/Library/Frameworks/OpenAL.framework; sourceTree = SDKROOT; };
 		D44C620D132DFF430009C878 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
 		D44C620F132DFF4E0009C878 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
@@ -386,6 +394,10 @@
 				2F15C5E52CB8F65A0057855D /* IAPCtlShopItem.cpp */,
 				C17946162CC7502600779B63 /* IAPTestCard.hpp */,
 				C17946152CC7502600779B63 /* IAPTestCard.cpp */,
+				C18082272CCB3338009DE140 /* IAPCardView.hpp */,
+				C18082262CCB3338009DE140 /* IAPCardView.cpp */,
+				C18082322CCB71D3009DE140 /* IAPTestCardViewDelegate.hpp */,
+				C18082312CCB71D3009DE140 /* IAPTestCardViewDelegate.cpp */,
 			);
 			path = Shop;
 			sourceTree = "<group>";
@@ -728,6 +740,8 @@
 				C17ACCBC2CB903BA0072A711 /* TestScene.cpp in Sources */,
 				E4D223402BD667D4006F1F8D /* AdUtilsInterstitial.cpp in Sources */,
 				E4D2234F2BD66CDE006F1F8D /* RedWise.cpp in Sources */,
+				C18082332CCB71D3009DE140 /* IAPTestCardViewDelegate.cpp in Sources */,
+				C18082282CCB3338009DE140 /* IAPCardView.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -737,6 +751,7 @@
 			files = (
 				2F15C5F42CB8F65A0057855D /* IAPCtlShop.cpp in Sources */,
 				E4D223412BD667D4006F1F8D /* AdUtilsInterstitial.cpp in Sources */,
+				C18082292CCB3338009DE140 /* IAPCardView.cpp in Sources */,
 				2F15C5F62CB8F65A0057855D /* IAPCtlShopUI.cpp in Sources */,
 				2F15C5FB2CB8F65A0057855D /* IAPProcess.cpp in Sources */,
 				E4D223432BD667D4006F1F8D /* AdUtilsVideo.cpp in Sources */,
@@ -754,6 +769,7 @@
 				2F15C5F82CB8F65A0057855D /* IAPUserData.cpp in Sources */,
 				C17ACCBD2CB903BA0072A711 /* TestScene.cpp in Sources */,
 				2F15C5F52CB8F65A0057855D /* IAPCtlArea23.cpp in Sources */,
+				C18082342CCB71D3009DE140 /* IAPTestCardViewDelegate.cpp in Sources */,
 				E4E7A1232BD75C3F00107AED /* RPRedAudio.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;