1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢
      選擇下列產(chǎn)品馬上在線溝通
      服務(wù)時間:8:30-17:00
      你可能遇到了下面的問題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
      iOS如何實現(xiàn)支持小數(shù)的星星評分組件

      這篇文章主要為大家展示了“iOS如何實現(xiàn)支持小數(shù)的星星評分組件”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“iOS如何實現(xiàn)支持小數(shù)的星星評分組件”這篇文章吧。

      10年積累的做網(wǎng)站、網(wǎng)站設(shè)計經(jīng)驗,可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認識你,你也不認識我。但先網(wǎng)站設(shè)計后付款的網(wǎng)站建設(shè)流程,更有賓川免費網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。

      實現(xiàn)后效果如下:

      iOS如何實現(xiàn)支持小數(shù)的星星評分組件

      單個星星的實現(xiàn)

      對于單個星星的實現(xiàn),先考慮星星有三個狀態(tài),完全置灰狀態(tài),完全高亮狀態(tài),根據(jù)百分比半高亮狀態(tài)。而我這邊用的是UIButton來實現(xiàn),因為UIButton本身已經(jīng)有普通,高亮,選擇的狀態(tài)。主要實現(xiàn)的就是百分比高亮狀態(tài)。我們可以根據(jù)百分比將圖像進行裁剪,讓新圖像的寬度只有百分比所占的整個圖像的寬度。但是這時候調(diào)用setImage,會發(fā)現(xiàn)圖片處于整個button中間。這是因為UIButton的imageView的contentMode默認是AspectFit的,而AspectFit是默認居中的。Contentmode中的UIViewContentModeLeft,是不會把長邊縮放到imageView的邊長的。況且,直接改變UIButton里的ImageView的ContentMode是沒有效果的。要通過UIControl的contentVerticalAlignment屬性(垂直)和contentHorizontalAlignment屬性(水平)來達到類似ImageView的contentMode的效果。但是這兩個屬性都沒有帶Fit后綴的選項,也就是說并不會根據(jù)邊長等比縮放。所以需要先把圖片縮放到和Button大小一致。

      iOS如何實現(xiàn)支持小數(shù)的星星評分組件

      之后,我們就可以按百分比裁剪圖片

      + (UIImage *)croppedImage:(UIImage *)image fraction:(CGFloat)fractonPart{
       CGFloat width = image.size.width * fractonPart * image.scale;
       CGRect newFrame = CGRectMake(0, 0, width , image.size.height * image.scale);
       CGImageRef resultImage = CGImageCreateWithImageInRect(image.CGImage, newFrame);
       UIImage *result = [UIImage imageWithCGImage:resultImage scale:image.scale orientation:image.imageOrientation];
       CGImageRelease(resultImage);
       return result;
      }

      并在BackgroundImage設(shè)置為灰色的星星圖像,設(shè)置為Button的highlighted狀態(tài)

      - (void)setFractionPart:(CGFloat)fractionPart{
       if (fractionPart == 0) {
       return;
       }
       UIImage *image = [CDZStarButton croppedImage:self.highlightedImage fraction:fractionPart];
       self.imageView.contentMode = UIViewContentModeScaleAspectFit;
       self.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
       self.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
       [self setImage:image forState:UIControlStateHighlighted];
       [self setBackgroundImage:self.normalImage forState:UIControlStateHighlighted];
       self.selected = NO;
       self.highlighted = YES;
      }

      而全高亮的狀態(tài)可以設(shè)置為UIButtonde點擊態(tài)

      - (void)setHighlightedImage:(UIImage *)highlightedImage{
       _highlightedImage = [CDZStarButton reSizeImage:highlightedImage toSize:self.frame.size];
       [self setImage:_highlightedImage forState:UIControlStateSelected];
      }

      而點擊事件交由給上層的UIControl去處理,因為點擊的時候,除了點擊的星星本身,之前的星星也應(yīng)該處于完全高亮狀態(tài)。在上層初始化按鈕的時候把其userInteractionEnabled屬性設(shè)置為NO即可,這樣觸摸事件就會忽略傳遞到Button去做事件處理,從而從響應(yīng)者鏈傳遞上去交由父視圖的UIControl處理。

      如果點擊到星星的一半,我們應(yīng)該把點擊點轉(zhuǎn)換成小數(shù)部分給上層。C語言的round函數(shù)可以四舍五入,這里的10代表保留一位小數(shù),可以根據(jù)實際情況保留位數(shù),一般評分很少需要更高精度的。

      - (CGFloat)fractionPartOfPoint:(CGPoint)point{
       CGFloat fractionPart = (point.x - self.frame.origin.x) / self.frame.size.width;
       return round(fractionPart * 10) / 10;
      }

      到這里一個可以顯示分數(shù)的星星按鈕就完成了,接下來就是在上層的UIControl去處理觸摸事件的響應(yīng)。

      UIControl部分的實現(xiàn)

      主要分兩塊,星星按鈕的布局,觸摸事件響應(yīng)。

      布局

      首先根據(jù)星星的數(shù)量一個個添加上視圖,用UIView的tag來表示對應(yīng)第幾個星星按鈕。

      - (void)setupView {
       for (NSInteger index = 0; index < self.numberOfStars; index++) {
        CDZStarButton *starButton = [CDZStarButton.alloc initWithSize:self.starSize];
        starButton.tag = index;
        starButton.normalImage = self.normalStarImage;
        starButton.highlightedImage = self.highlightedStarImage;
        starButton.userInteractionEnabled = NO;//關(guān)閉事件響應(yīng),交由UIControl本身處理
        [self addSubview:starButton];
       }
      }

      然后是計算每個星星的位置,計算間隔和上下邊距并layout

      - (void)layoutSubviews {
       [super layoutSubviews];
       for (NSInteger index = 0; index < self.numberOfStars; index ++) {
        CDZStarButton *starButton = [self starForTag:index];
        CGFloat newY = (self.frame.size.height - self.starSize.height) / 2;
        CGFloat margin = 0;
        if (self.numberOfStars > 1) {
         margin = (self.frame.size.width - self.starSize.width * self.numberOfStars) / (self.numberOfStars - 1);
        }
        starButton.frame = CGRectMake((self.starSize.width + margin) * index, newY, self.starSize.width, self.starSize.height);
       }
      }

      這時,我們可以加上兩個方法去找到對應(yīng)的星星button,根據(jù)tag和根據(jù)點擊的CGPoint

      - (CDZStarButton *)starForPoint:(CGPoint)point {
       for (NSInteger i = 0; i < self.numberOfStars; i++) {
        CDZStarButton *starButton = [self starForTag:i];
        if (CGRectContainsPoint(starButton.frame, point)) {
         return starButton;
        }
       }
       return nil;
      }
      
      - (CDZStarButton *)starForTag:(NSInteger)tag {
       __block UIView *target;
       [self.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if (obj.tag == tag) {
         target = obj;
         *stop = YES;
        }
       }];
       return (CDZStarButton *)target;
      }

      處理觸摸事件

      我們先加上兩個方法。一個是從第一個到某個星星開始從左到右依次點亮,一個是從最后一個星星到某個星星從右到左依次熄滅。

      - (void)starsDownToIndex:(NSInteger)index {
       for (NSInteger i = self.numberOfStars; i > index; --i) {
        CDZStarButton *starButton = [self starForTag:i];
        starButton.selected = NO;
        starButton.highlighted = NO;
       }
      }
      
      - (void)starsUpToIndex:(NSInteger)index {
       for (NSInteger i = 0; i <= index; i++) {
        CDZStarButton *starButton = [self starForTag:i];
        starButton.selected = YES;
        starButton.highlighted = NO;
       }
      }

      然后設(shè)置一個評分的屬性,重寫其setter方法。allowFraction,用來判斷組件是否需要分數(shù)表示,floor函數(shù)是取最大整數(shù),相當(dāng)于直接去除小數(shù)點后面的數(shù)字。判斷評分的整數(shù)部分是否已經(jīng)亮著,亮著那么說明從左到右最后一個亮著的右邊,反之在左邊,分別調(diào)用從右到左依次熄滅,或從左到右依次點亮的方法,最后再設(shè)置分數(shù)部分。

      - (void)setScore:(CGFloat)score{
       if (_score == score) {
        return;
       }
       _score = score;
       NSInteger index = floor(score);
       CGFloat fractionPart = score - index;;
       if (!self.isAllowFraction || fractionPart == 0) {
        index -= 1;
       }
       CDZStarButton *starButton = [self starForTag:index];
       if (starButton.selected) {
        [self starsDownToIndex:index];
       }
       else{
        [self starsUpToIndex:index];
       }
       starButton.fractionPart = fractionPart;
      }

      主要用到UIControl的四個方法

      iOS如何實現(xiàn)支持小數(shù)的星星評分組件

      第一個是開始點擊的時候的事件處理,第二個是手指未抬起在屏幕上繼續(xù)移動的事件處理,第三個是離開屏幕,第四個是因為別的特殊情況事件被結(jié)束的處理。

      點擊時候只要確定點擊的星星,確定其小數(shù)部分,然后調(diào)用評分屬性的setter方法就好了。

      - (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
       CGPoint point = [touch locationInView:self];
       CDZStarButton *pressedStar = [self starForPoint:point];
       if (pressedStar) {
        self.currentStar = pressedStar;
        NSInteger index = pressedStar.tag;
        CGFloat fractionPart = 1;
        if (self.isAllowFraction) {
         fractionPart = [pressedStar fractionPartOfPoint:point];
        }
        self.score = index + fractionPart;
       }
       return YES;
      }

      移動處理除了和點擊一樣的判斷邏輯,還要注意手指移開了星星之外的地方,分為所在星星的左邊(當(dāng)前星星熄滅),右邊(當(dāng)前星星完全點亮)兩種。

      - (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
       CGPoint point = [touch locationInView:self];
       CDZStarButton *pressedStar = [self starForPoint:point];
       if (pressedStar) {
        self.currentStar = pressedStar;
        NSInteger index = pressedStar.tag;
        CGFloat fractionPart = 1;
        if (self.isAllowFraction) {
         fractionPart = [pressedStar fractionPartOfPoint:point];
        }
        self.score = index + fractionPart;
       }
       else{
         //移到了當(dāng)前星星的左邊
        if (point.x < self.currentStar.frame.origin.x) {
         self.score = self.currentStar.tag;
        }
         //移到了當(dāng)前星星的右邊
        else if (point.x > (self.currentStar.frame.origin.x + self.currentStar.frame.size.width)){
         self.score = self.currentStar.tag + 1;
        }
       }
       return YES;
      }

      而完成觸摸操作時,我們就可以用一個回調(diào)將當(dāng)前的評分傳給外界。

      @protocol CDZStarsControlDelegate
      @optional
      
      /**
       回調(diào)星星改變后的分數(shù)
      
       @param starsControl 星星組件
       @param score 分數(shù)
       */
      - (void)starsControl:(CDZStarsControl *)starsControl didChangeScore:(CGFloat)score;
      @end
      - (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
       [super endTrackingWithTouch:touch withEvent:event];
       if ([self.delegate respondsToSelector:@selector(starsControl:didChangeScore:)]) {
        [self.delegate starsControl:self didChangeScore:self.score];
       }
      }
      
       
      
      - (void)cancelTrackingWithEvent:(UIEvent *)event {
       [super cancelTrackingWithEvent:event];
       if ([self.delegate respondsToSelector:@selector(starsControl:didChangeScore:)]) {
        [self.delegate starsControl:self didChangeScore:self.score];
       }
      }

      封裝

      - (instancetype)initWithFrame:(CGRect)frame
            stars:(NSInteger)number
            starSize:(CGSize)size
          noramlStarImage:(UIImage *)normalImage
         highlightedStarImage:(UIImage *)highlightedImage{
       if (self = [super initWithFrame:frame]) {
        _numberOfStars = number;
        _normalStarImage = normalImage;
        _highlightedStarImage = highlightedImage;
        _starSize = size;
        _allowFraction = NO;
        self.clipsToBounds = YES;
        self.backgroundColor = [UIColor clearColor];
        [self setupView];
       }
       return self;
      }

      開放score屬性和allowFraction屬性即可。使用起來也很簡單。

       CDZStarsControl *starsControl = [CDZStarsControl.alloc initWithFrame:CGRectMake(0, 100, self.view.frame.size.width, 50) stars:5 starSize:CGSizeMake(50, 50) noramlStarImage:[UIImage imageNamed:@"star_normal"] highlightedStarImage:[UIImage imageNamed:@"star_highlighted"]];
       starsControl.delegate = self;
       starsControl.allowFraction = YES;
       starsControl.score = 2.6f;
       [self.view addSubview:starsControl];

      然后在delegate里處理分數(shù)改變后的操作即可。

      以上是“iOS如何實現(xiàn)支持小數(shù)的星星評分組件”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!


      網(wǎng)頁標題:iOS如何實現(xiàn)支持小數(shù)的星星評分組件
      轉(zhuǎn)載注明:http://www.ef60e0e.cn/article/iegchd.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        阜宁县| 潞城市| 扶风县| 林西县| 嘉祥县| 类乌齐县| 砚山县| 铜山县| 昭平县| 加查县| 淳化县| 张家界市| 得荣县| 额济纳旗| 寿宁县| 丽江市| 苍山县| 商洛市| 长海县| 林州市| 武汉市| 祁阳县| 攀枝花市| 潢川县| 射阳县| 峨边| 保定市| 香格里拉县| 无锡市| 晋宁县| 高碑店市| 镇原县| 遂溪县| 浦城县| 灵台县| 庄浪县| 神木县| 大姚县| 彩票| 虎林市| 色达县|