zoukankan      html  css  js  c++  java
  • iOS UICollectionView实现动态标签(单选、多选)

    项目中我们经常会遇到标签动态展示的问题,有时我们也需要实现单选或者多选的功能

    <1> 针对标签动态展示,我们解决的核心办法就是动态计算文本宽度

    即:标签宽度=文本宽度+左右间距

    核心代码:

    #pragma mark -- UICollectionViewDelegateFlowLayout
    - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        TaskValueModel *model = self.model.orgRelationCollection[indexPath.row];
        NSString *str = ObjErrorCheck(model.value);
       // 核心代码 动态宽度计算
       //  LL_ScreenWidth -74 (文本最大宽度)最大就是一行放置一个
        CGRect itemFrame = [str boundingRectWithSize:CGSizeMake(LL_ScreenWidth -74, 14) options: NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:14]} context:nil];
       //  item的宽度 文本宽度+左右间距合计24
        CGFloat width = itemFrame.size.width + 24;
        //  item的size
        return CGSizeMake(width, 32);
    }

    <2> 针对单选或者多选,核心就是在标签模型上的selected标记,然后根据操作改变这个值

    单选核心代码

    #pragma mark -- UICollectionViewDelegate
    - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
        //  单选功能
        TaskValueModel *model = self.model.orgRelationCollection[indexPath.row];
        //  选中再次点击取消选中
        if (model.selected) {
            model.selected = !model.selected;
        //  未选中点击选中,同时确保其它未选中
        } else {
            [self.model.orgRelationCollection enumerateObjectsUsingBlock:^(TaskValueModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                if (model.id == obj.id) {
                    obj.selected  = YES;
                }else {
                    obj.selected  = NO;
                }
            }];
        }
        [self.collectionView reloadData];
        
    }

    多选核心代码

    #pragma mark -- UICollectionViewDelegate
    - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
        //    多选实现
        TaskValueModel *model = self.model.valueTypeCollection[indexPath.row];
        model.selected = !model.selected;
        [self.collectionView reloadData];
        
    }

     注意点:

    文本的最大宽度LL_ScreenWidth -74 (文本最大宽度)最大就是一行放置一个

    计算高度时的最大宽度(xOffset + 当前item的宽):LL_ScreenWidth -50  最大宽度(collectionView的宽度)

    今天我就简述下使用UICollectionView实现上述功能,

    1、自定义布局 LeftAlignFlowLayout

    2、自定义标签 ValueTypeCollectionViewCell

    3、标签对应的模型 TaskValueModel(因为我们需要在模型中记录选中未选状态,并且会做修改,所以不建议使用NSDictionary,不然修改会比较麻烦

    4、多选功能(未选点击选中,再次点击取消选中

    5、单选功能(未选点击选中且保证其它是未选中,再次点击取消选中ValueTypeTableViewCell

    效果如图:

    话不多说,直接上代码

    一、自定义布局LeftAlignFlowLayout

    LeftAlignFlowLayout.h

    //
    //  LeftAlignFlowLayout.h
    //  CollectionViewDemo
    //
    //  Created by LJY on 2017/8/24.
    //  Copyright © 2017年 LJY. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @interface LeftAlignFlowLayout : UICollectionViewFlowLayout
    
    /**
     *  可以通过UICollectionViewFlowLayout的属性,或者UICollectionViewDelegateFlowLayout的方法设置布局属性。皆不设置
     *  采用系统默认值。
     */
    + (instancetype) leftAlignLayoutWithDelegate:(id<UICollectionViewDelegateFlowLayout>) delegate;
    
    @end

    LeftAlignFlowLayout.m

    //
    //  LeftAlignFlowLayout.m
    //  CollectionViewDemo
    //
    //  Created by LJY on 2017/8/24.
    //  Copyright © 2017年 LJY. All rights reserved.
    //
    
    #import "LeftAlignFlowLayout.h"
    
    @interface LeftAlignFlowLayout ()
    
    @property (nonatomic, weak) id<UICollectionViewDelegateFlowLayout> delegate;
    @property (nonatomic, strong) NSMutableArray *arrForItemAtrributes;
    
    @end
    
    @implementation LeftAlignFlowLayout
    
    + (instancetype) leftAlignLayoutWithDelegate:(id<UICollectionViewDelegateFlowLayout>) delegate
    {
        LeftAlignFlowLayout* layout = [[LeftAlignFlowLayout alloc] init];
        layout.delegate = delegate;
        return layout;
    }
    
    #pragma mark Override method
    - (void)prepareLayout
    {
        [super prepareLayout];
        CGFloat xForItemOrigin = self.sectionInsetCustomer.left;
        CGFloat yForItemOrigin = self.sectionInsetCustomer.top;
        CGFloat itemHeight = [self itemSizeCustomer:[NSIndexPath indexPathForRow:0 inSection:0]].height;
        CGFloat xOffset = self.sectionInsetCustomer.left;
        NSUInteger numberOfItems = [self.collectionView numberOfItemsInSection:0];
        NSUInteger numberOfRows = 0;
        self.arrForItemAtrributes = [NSMutableArray arrayWithCapacity:numberOfItems];
        // 为每个item确定LayoutAttribute属性,同时将这些属性放入布局数组中 
        for(int i = 0; i <numberOfItems; i++)
        {
            NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
            UICollectionViewLayoutAttributes *layoutArr = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
            CGFloat itemWidth = [self itemSizeCustomer:indexPath].width;;
            //xOffset + 当前item的宽 <= 最大宽度
            if ((xOffset + itemWidth) <= (self.collectionView.bounds.size.width - self.sectionInsetCustomer.right - self.sectionInsetCustomer.left))
            {
                //设置x
                xForItemOrigin = xOffset;
                xOffset += itemWidth + self.minimumInteritemSpacingCustomer;
            }
            else
            {
                //换行
                xForItemOrigin = self.sectionInsetCustomer.left;
                xOffset  = self.sectionInsetCustomer.left + itemWidth + self.minimumInteritemSpacingCustomer;
                numberOfRows++;
            }
            // 设置y
            yForItemOrigin = self.sectionInsetCustomer.top + (itemHeight+ self.minimumLineSpacingCustomer) * numberOfRows;
            layoutArr.frame = CGRectMake(xForItemOrigin, yForItemOrigin, itemWidth, itemHeight);
            [self.arrForItemAtrributes addObject:layoutArr];
        }
    }
    
    - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
    {
        return self.arrForItemAtrributes;
    }
    
    #pragma mark - Inner method
    /**
     *  default 10
     */
    - (CGFloat)minimumLineSpacingCustomer
    {
        if (self.delegate && [self.delegate respondsToSelector:@selector(collectionView:layout:minimumLineSpacingForSectionAtIndex:)])
        {
            return [self.delegate collectionView:self.collectionView layout:self minimumLineSpacingForSectionAtIndex:0];
        }
        else
        {
            return self.minimumLineSpacing;
        }
    }
    /**
     *  default 10
     */
    - (CGFloat)minimumInteritemSpacingCustomer
    {
        if (self.delegate && [self.delegate respondsToSelector:@selector(collectionView:layout:minimumInteritemSpacingForSectionAtIndex:)])
        {
            return [self.delegate collectionView:self.collectionView layout:self minimumInteritemSpacingForSectionAtIndex:0];
        }
        else
        {
            return self.minimumInteritemSpacing;
        }
    }
    /**
     *  default UIEdgeInsetsZero
     */
    - (UIEdgeInsets)sectionInsetCustomer
    {
        if (self.delegate && [self.delegate respondsToSelector:@selector(collectionView:layout:insetForSectionAtIndex:)])
        {
            return [self.delegate collectionView:self.collectionView layout:self insetForSectionAtIndex:0];
        }
        else
        {
            return self.sectionInset;
        }
    
    }
    /**
     *  default {50, 50}
     */
    - (CGSize)itemSizeCustomer:(NSIndexPath *)indexPath
    {
        if (self.delegate && [self.delegate respondsToSelector:@selector(collectionView:layout:sizeForItemAtIndexPath:)])
        {
            return [self.delegate collectionView:self.collectionView layout:self sizeForItemAtIndexPath:indexPath];
        }
        else
        {
            return self.itemSize;
        }
    }
    /**
     *  default CGSizeZero
     */
    - (CGSize)headerReferenceSizeCustomer
    {
        if (self.delegate && [self.delegate respondsToSelector:@selector(collectionView:layout:referenceSizeForHeaderInSection:)])
        {
            return [self.delegate collectionView:self.collectionView layout:self referenceSizeForHeaderInSection:0];
        }
        else
        {
            return self.headerReferenceSize;
        }
    }
    /**
     *  default CGSizeZero
     */
    - (CGSize)footerReferenceSizeCustomer
    {
        if (self.delegate && [self.delegate respondsToSelector:@selector(collectionView:layout:referenceSizeForFooterInSection:)])
        {
            return [self.delegate collectionView:self.collectionView layout:self referenceSizeForFooterInSection:0];
        }
        else
        {
            return self.footerReferenceSize;
        }
    }
    
    @end

    二、自定义标签ValueTypeCollectionViewCell

    ValueTypeCollectionViewCell.h

    #import <UIKit/UIKit.h>
    #import "iCCarrerCircleTaskDetailsNewModel.h"
    NS_ASSUME_NONNULL_BEGIN
    static NSString  *const ValueTypeCollectionViewCellReused     = @"ValueTypeCollectionViewCell";
    @interface ValueTypeCollectionViewCell : UICollectionViewCell
    - (void)configCell:(TaskValueModel *)model;
    @end

    ValueTypeCollectionViewCell.m

    #import "ValueTypeCollectionViewCell.h"
    
    @interface ValueTypeCollectionViewCell ()
    @property (nonatomic, strong) UIView *bgView;
    @property (nonatomic, strong) UILabel *tagLabel;
    @property (nonatomic, strong) UIImageView *rightIcon;
    @end
    
    @implementation ValueTypeCollectionViewCell
    
    #pragma mark - System
    
    - (instancetype)initWithFrame:(CGRect)frame {
         
        self = [super initWithFrame:frame];
        if (self) {
            [self initData];
            [self initUI];
        }
        return self;
    }
    
    #pragma mark - Init Data
    
    - (void)initData {
        
    }
    
    #pragma mark - Init UI
    
    - (void)initUI {
        
        self.backgroundColor = [UIColor clearColor];
        
        [self.contentView addSubview:self.bgView];
        [self.bgView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.edges.equalTo(self.contentView);
        }];
        
        [self.bgView addSubview:self.rightIcon];
        [self.rightIcon mas_makeConstraints:^(MASConstraintMaker *make) {
            make.right.equalTo(self.bgView);
            make.top.equalTo(self.bgView);
            make.width.height.mas_equalTo(19);
        }];
        
        [self.bgView addSubview:self.tagLabel];
        [self.tagLabel mas_makeConstraints:^(MASConstraintMaker *make) {
            make.center.equalTo(self.bgView);
        }];
        
    }
    
    - (UIView *)bgView {
        if (!_bgView) {
            _bgView = [[UIView alloc] init];
            [_bgView cornerAngel:5];
        }
        return _bgView;
    }
    
    - (UILabel *)tagLabel {
        if(!_tagLabel){
            _tagLabel = [[UILabel alloc]init];
            _tagLabel.font = FF_PFR_ICOME(14);
        }
        return _tagLabel;
    }
    
    - (UIImageView *)rightIcon {
        if(!_rightIcon){
            _rightIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"task_value_sel"]];
        }
        return _rightIcon;
    }
    
    #pragma mark - Reload View
    - (void)configCell:(TaskValueModel *)model {
        self.tagLabel.text = ObjErrorCheck(model.value);
        
        if (model.allowdClick) {
            
            if (model.selected) {
    //            选中样式
                self.bgView.backgroundColor = CC_ICOME(@"#3480FF1A");
                [self.bgView borderWidth:ONE_PIXEL andBorderColor:CC_ICOME(@"#3480FF33")];
                self.tagLabel.textColor = CC_ICOME(@"#3480FF");
                self.rightIcon.hidden = NO;
                
            } else {
    //         未选中样式
                self.bgView.backgroundColor = XZWL_COLOR_FFFFFF;
                [self.bgView borderWidth:ONE_PIXEL andBorderColor:CC_ICOME(@"#BBBBBB")];
                self.tagLabel.textColor = CC_ICOME(@"#666666");
                self.rightIcon.hidden = YES;
            }
            
        } else {
    //        不可点击样式
            self.bgView.backgroundColor = CC_ICOME(@"#3480FF1A");
            [self.bgView borderWidth:ONE_PIXEL andBorderColor:CC_ICOME(@"#3480FF33")];
            self.tagLabel.textColor = CC_ICOME(@"#3480FF");
            self.rightIcon.hidden = YES;
        }
        
    }
    
    @end

    三、标签对应模型TaskValueModel

    TaskValueModel.h

    @protocol TaskValueModel
    @end
    @interface TaskValueModel : JSONModel
    @property (nonatomic, copy) NSString *value;//
    @property (nonatomic, assign) NSInteger id;//
    @property (nonatomic, assign) BOOL selected;//
    @property (nonatomic, assign) BOOL allowdClick;//
    @end

    四、单选功能卡片ValueTypeTableViewCell

    ValueTypeTableViewCell.h

    #import "BaseTableViewCell.h"
    #import "iCCarrerCircleTaskDetailsNewModel.h"
    NS_ASSUME_NONNULL_BEGIN
    
    @interface ValueTypeTableViewCell : BaseTableViewCell
    + (CGFloat)getCellHeight:(iCCarrerCircleTaskDetailsNewModel *)model;
    
    - (void)configCell:(iCCarrerCircleTaskDetailsNewModel *)model;
    @end

    ValueTypeTableViewCell.m

    #import "ValueTypeTableViewCell.h"
    #import "ValueTypeCollectionViewCell.h"
    #import "LeftAlignFlowLayout.h"
    
    @interface ValueTypeTableViewCell ()<UICollectionViewDelegateFlowLayout,UICollectionViewDelegate, UICollectionViewDataSource>
    @property (nonatomic, strong) UIView *bgView;
    @property (nonatomic, strong) UIImageView *LImage;
    @property (nonatomic, strong) UILabel *LLab;
    @property (nonatomic, strong) UICollectionView *collectionView;
    @property (nonatomic, strong) iCCarrerCircleTaskDetailsNewModel *model;
    @end
    
    @implementation ValueTypeTableViewCell
    #pragma mark - System
    
    - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
        self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
        if (self) {
            [self initUI];
        }
        return self;
    }
    
    #pragma mark - Init Data
    
    - (void)initData {
    }
    
    #pragma mark - Init UI
    
    - (void)initUI {
        self.accessoryType = UITableViewCellAccessoryNone;
        self.selectionStyle = UITableViewCellSelectionStyleNone;
        self.backgroundColor = [UIColor clearColor];
        
        [self.contentView addSubview:self.bgView];
        [self.bgView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(self.contentView.mas_top);
            make.left.equalTo(self.contentView.mas_left).offset(10);
            make.right.equalTo(self.contentView.mas_right).offset(-10);
            make.bottom.equalTo(self.contentView);
        }];
        
        [self.bgView addSubview:self.LImage];
        [self.LImage mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.equalTo(self.bgView).offset(15);
            make.top.equalTo(self.bgView).offset(17);
            make.height.mas_equalTo(17);
            make.width.mas_equalTo(16);
        }];
        
        [self.bgView addSubview:self.LLab];
        [self.LLab mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.equalTo(self.bgView).offset(44);
            make.centerY.equalTo(self.LImage);
        }];
        
        [self.bgView addSubview:self.collectionView];
        [self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.equalTo(self.bgView).offset(15);
            make.top.equalTo(self.bgView).offset(52);
            make.bottom.equalTo(self.bgView).offset(-20);
            make.right.equalTo(self.bgView).offset(-15);
        }];
        
    }
    
    - (UIView *)bgView {
        if (!_bgView) {
            _bgView = [[UIView alloc] init];
            _bgView.backgroundColor = XZWL_COLOR_FFFFFF;
            [_bgView cornerAngel:8];
        }
        return _bgView;
    }
    
    - (UILabel *)LLab {
        if (!_LLab) {
            _LLab = [[UILabel alloc]init];
            _LLab.font = FF_PFM_ICOME(16);
            _LLab.textColor = XZWL_COLOR_333333;
            _LLab.text = @"单选测试";
        }
        return _LLab;
    }
    
    - (UIImageView *)LImage {
        if (!_LImage) {
            _LImage = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"task_org"]];
        }
        return _LImage;
    }
    
    - (UICollectionView *)collectionView {
        
        if (!_collectionView) {
           //   核心代码 自定义布局LeftAlignFlowLayout
            LeftAlignFlowLayout *layout = [LeftAlignFlowLayout leftAlignLayoutWithDelegate:self];
            layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
            
            _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
            _collectionView.delegate = self;
            _collectionView.dataSource = self;
            _collectionView.showsHorizontalScrollIndicator = NO;
            _collectionView.showsVerticalScrollIndicator = NO;
            _collectionView.backgroundColor = [UIColor clearColor];
            
            [_collectionView registerClass:[ValueTypeCollectionViewCell class] forCellWithReuseIdentifier:ValueTypeCollectionViewCellReused];
            
            if (@available(iOS 11.0, *)) {
                _collectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
            } else {
                self.viewController.automaticallyAdjustsScrollViewInsets = NO;
            }
            
        }
        return _collectionView;
    }
    
    #pragma mark - Event
    
    #pragma mark - DataSource
    #pragma mark -- UICollectionViewDataSource
    - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
        return 1;
    }
    
    - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
        return self.model.orgRelationCollection.count;
    }
    
    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
        ValueTypeCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:ValueTypeCollectionViewCellReused forIndexPath:indexPath];
        TaskValueModel *model = self.model.orgRelationCollection[indexPath.row];
        [cell configCell:model];
        return cell;
    }
    
    #pragma mark - Delegate
    #pragma mark -- UICollectionViewDelegate
    - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
        //  单选功能
        TaskValueModel *model = self.model.orgRelationCollection[indexPath.row];
        //  选中再次点击取消选中
        if (model.selected) {
            model.selected = !model.selected;
        //  未选中点击选中,同时确保其它未选中
        } else {
            [self.model.orgRelationCollection enumerateObjectsUsingBlock:^(TaskValueModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                if (model.id == obj.id) {
                    obj.selected  = YES;
                }else {
                    obj.selected  = NO;
                }
            }];
        }
        [self.collectionView reloadData];
        
    }
    #pragma mark -- UICollectionViewDelegateFlowLayout
    - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        TaskValueModel *model = self.model.orgRelationCollection[indexPath.row];
        NSString *str = ObjErrorCheck(model.value);
       // 核心代码 动态宽度计算
       //  LL_ScreenWidth -74 (文本的最大宽度)最大就是一行放置一个
        CGRect itemFrame = [str boundingRectWithSize:CGSizeMake(LL_ScreenWidth -74, 14) options: NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:14]} context:nil];
       //  item的宽度 文本宽度+左右间距合计24
        CGFloat width = itemFrame.size.width + 24;
        //  item的size
        return CGSizeMake(width, 32);
    }
    
    #pragma mark - Reload View
    + (CGFloat)getCellHeight:(iCCarrerCircleTaskDetailsNewModel *)model {
        CGFloat heightmp = 0;
        // 核心代码 高度计算
        if (model.orgRelationCollection.count) {
            // itemSizes 存放itemsize的集合
            NSMutableArray *itemSizes = [NSMutableArray array];
            for (TaskValueModel *modelt in model.orgRelationCollection)
            {
                CGRect itemFrame = [ObjErrorCheck(modelt.value) boundingRectWithSize:CGSizeMake(LL_ScreenWidth -74, 14) options: NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:14]} context:nil];
                
                CGFloat width = itemFrame.size.width + 24;
                NSValue *itemSize =[NSValue valueWithCGSize:CGSizeMake(width, 32)];
                [itemSizes addObject:itemSize];
            }
            
            NSInteger row = 1;
            CGFloat xOffset = 0 ;
           //  单个item高度
            CGFloat height = 32;
            for(int i = 0; i <itemSizes.count; i++)
            {
                CGFloat itemWidth = [itemSizes[i] CGSizeValue].width;
                //xOffset + 当前item的宽 <= 最大宽度(collectionView的宽度)
                if ((xOffset + itemWidth) <= (LL_ScreenWidth - 50))
                {
                    xOffset += itemWidth + 10;
                }
                else
                {
                    //换行
                    xOffset  = itemWidth + 10;
                    row++;
                }
            }
            //   collectionview高度: 行数 * 行高 + (行数 - 1)*行间距
            CGFloat maxHeight = row * height + (row - 1) * 10 ;
            //  总高度: collectionview高度 + 上下间距
            heightmp = maxHeight + 72;
            
        }
        return heightmp;
        
    }
    
    - (void)configCell:(iCCarrerCircleTaskDetailsNewModel *)model{
        self.model = model;
        self.collectionView.userInteractionEnabled = NO;
        if (self.model.orgRelationCollection.count) {
            TaskValueModel *modelt=self.model.orgRelationCollection[0];
            if (modelt.allowdClick) {
                self.collectionView.userInteractionEnabled = YES;
            }
            self.hidden = NO;
            [self.collectionView reloadData];
        } else {
            self.hidden = YES;
        }
        
    }
    
    @end

    五、多选功能与单选相似,只是处理选中逻辑不同

    - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
        //    多选实现
        TaskValueModel *model = self.model.valueTypeCollection[indexPath.row];
        model.selected = !model.selected;
        [self.collectionView reloadData];
        
    }
  • 相关阅读:
    Android_EditText 密码框默认是小圆点 怎么改成其它的(*)?
    Android_view的生命周期
    Android_对android虚拟机的理解,包括内存管理机制垃圾回收机制。dalvik和art区别
    Android_触摸事件传递机制
    Android_OnLowMemory和OnTrimMemory
    Android_ FragmentTabHost切换Fragment时避免重复加载UI
    位运算&字节运算
    C#编程简短总结
    IOS随机随学
    计算机图形学
  • 原文地址:https://www.cnblogs.com/lijianyi/p/15007758.html
Copyright © 2011-2022 走看看