enda

enda 查看完整档案

北京编辑中央财经大学  |  项目管理 编辑CSXINO  |  CEO 编辑 www.phpcto.org 编辑
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 个人简介什么都没有

个人动态

enda 回答了问题 · 2020-10-15

swift的uiview点击事件怎么传参数?

阅读量还是挺高的,看来不少人遇到了这个问题;我也是在寻找 UIView 点击事件的参数传递;目前我通过 tag 解决了

UIButton 的点击参数传递

设置 UIButtontag,详细见代码

let playButton = UIButton(type: .custom)
playButton.setTitle("开始播放", for: .normal)
playButton.backgroundColor = UIColor(white: 1.0, alpha: 0.8)
playButton.layer.cornerRadius = 17.5
playButton.tag = index // 关键在这一行
playButton.addTarget(self, action: #selector(playClicked(button:)), for: .touchUpInside)
itemView.addSubview(playButton)

接收


@objc func playClicked(button: UIButton){
    print(button.tag)
}

UIView 的点击事件与传输传递

UIView 是没有点击事件这个东西的,不过我们可以用 UITapGestureRecognizer 手势来解决

详细见代码

let itemView = UIView()
itemView.isUserInteractionEnabled = true

itemView.tag = index  // 传输传递

// 创建手势
let tap = UITapGestureRecognizer(target: self, action:#selector(tapClick(sender:)))

// 添加到 UIView 上
itemView.addGestureRecognizer(tap)
homeMusicScrollView.addSubview(itemView)

接收

同样的道理


@objc func tapClick(sender: UIGestureRecognizer){
    let itemView = sender.view!
    print(itemView.tag)
}

关注 1 回答 1

enda 发布了文章 · 2020-10-15

swift5.3 UIView 与 UIButton 点击事件传递参数

UIViewUIbutton 点击事件的参数传递;目前我通过 tag 解决了

UIButton 的点击参数传递

设置 UIButtontag,详细见代码

let playButton = UIButton(type: .custom)
playButton.setTitle("开始播放", for: .normal)
playButton.backgroundColor = UIColor(white: 1.0, alpha: 0.8)
playButton.layer.cornerRadius = 17.5

// 关键在这一行
playButton.tag = index 

playButton.addTarget(self, action: #selector(playClicked(button:)), for: .touchUpInside)
itemView.addSubview(playButton)

接收


@objc func playClicked(button: UIButton){
    print(button.tag)
}

UIView 的点击事件与传输传递

UIView 是没有点击事件这个东西的,不过我们可以用 UITapGestureRecognizer 手势来解决

详细见代码

let itemView = UIView()
itemView.isUserInteractionEnabled = true

itemView.tag = index  // 传输传递

// 创建手势
let tap = UITapGestureRecognizer(target: self, action:#selector(tapClick(sender:)))

// 添加到 UIView 上
itemView.addGestureRecognizer(tap)
homeMusicScrollView.addSubview(itemView)

接收

同样的道理


@objc func tapClick(sender: UIGestureRecognizer){
    let itemView = sender.view!
    print(itemView.tag)
}
查看原文

赞 0 收藏 0 评论 0

enda 发布了文章 · 2020-10-13

swift5.3 UIScrollView 动态计算 contentSize

UIScrollView 的特殊之处就在于当它遇到了AutoLayout之后其contentSize 的计算规则有些特殊。
contentSize是根据子视图的leading/trailing/top/bottom进行确定的

所以避免我们手动去设置 contentSize,我们必须迎合它的规则去设置

直接上代码


       let scrollView = UIScrollView()
        
        scrollView.backgroundColor = .gray
        view.addSubview(scrollView)
        scrollView.snp.makeConstraints { (make) in
            make.edges.equalToSuperview()
        }
        let containerView = UIView()
        containerView.backgroundColor = .blue
        scrollView.addSubview(containerView)
        containerView.snp.makeConstraints { (make) in
            make.edges.equalToSuperview()
            make.width.equalToSuperview()
        }
        
        let view1 = UIView()
        view1.backgroundColor = .orange
        
        let view2 = UIView()
        view2.backgroundColor = .blue
        
        
        containerView.addSubview(view1)
        containerView.addSubview(view2)
        
        view1.snp.makeConstraints { (make) in
            make.top.equalToSuperview()
            make.width.equalToSuperview()
            make.height.equalTo(500)
        }
        
        view2.snp.makeConstraints { (make) in
            make.top.equalTo(view1.snp.bottom)
            make.bottom.equalTo(containerView.snp.bottom)
            make.leading.trailing.equalTo(containerView)
            make.width.equalToSuperview()
            make.height.equalTo(500)
        }

大概就是这意思,我们通过一个填满的 containerView 去设置子视图,同时我们最后一个 subviewbottom 一定要与 containerView 对齐即可

查看原文

赞 0 收藏 0 评论 0

enda 发布了文章 · 2020-10-12

swift5.3 UIColor 使用十六进制颜色

本文环境

  • Xcode 12
  • Swift 5.3
  • iOS 13

UI 给出的颜色往往都是十六进制的,如 #1a1a1a 等,但是我们在 iOS中是不能直接使用的,查询了一些代码,发现比较老旧,这里给出一个改进版本

使用 Extension 扩展

新建一个 swift 文件

比如我的 string.swift ,复制以下代码

//
//  String.swift
//  bestWhiteNoise
//
//  Created by 袁超 on 2020/10/10.
//

import Foundation
import UIKit

extension String {
    /// 十六进制字符串颜色转为UIColor
    /// - Parameter alpha: 透明度
    func uicolor(alpha: CGFloat = 1.0) -> UIColor {
        // 存储转换后的数值
        var red: UInt64 = 0, green: UInt64 = 0, blue: UInt64 = 0
        var hex = self
        // 如果传入的十六进制颜色有前缀,去掉前缀
        if hex.hasPrefix("0x") || hex.hasPrefix("0X") {
            hex = String(hex[hex.index(hex.startIndex, offsetBy: 2)...])
        } else if hex.hasPrefix("#") {
            hex = String(hex[hex.index(hex.startIndex, offsetBy: 1)...])
        }
        // 如果传入的字符数量不足6位按照后边都为0处理,当然你也可以进行其它操作
        if hex.count < 6 {
            for _ in 0..<6-hex.count {
                hex += "0"
            }
        }

        // 分别进行转换
        // 红
        Scanner(string: String(hex[..<hex.index(hex.startIndex, offsetBy: 2)])).scanHexInt64(&red)
        // 绿
        Scanner(string: String(hex[hex.index(hex.startIndex, offsetBy: 2)..<hex.index(hex.startIndex, offsetBy: 4)])).scanHexInt64(&green)
        // 蓝
        Scanner(string: String(hex[hex.index(startIndex, offsetBy: 4)...])).scanHexInt64(&blue)

        return UIColor(red: CGFloat(red)/255.0, green: CGFloat(green)/255.0, blue: CGFloat(blue)/255.0, alpha: alpha)
    }
}

使用

比如 UI 给的颜色是 #5188e1, 那么我们直接使用字符的扩展函数即可

"5188e1".uicolor()

如设置 TabBarItem 的字体颜色

item.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: "5188e1".uicolor()], for: .selected)
uicolor 函数也是在网上找到的,之前的函数在 iOS 13 中,scanHexInt34 方法被废弃,故此方法适配了 iOS 13
查看原文

赞 0 收藏 0 评论 1

enda 发布了文章 · 2020-10-12

解决 Xcode12+swift 5 使用 pod 出现警告的问题

起因

在新建项目后,使用 pod 安装一些组件,结果出现了如下错误

Pod installation complete! There is 1 dependency from the Podfile and 1 total pod installed.

[!] The `bestWhiteNoise [Debug]` target overrides the `ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES` build setting defined in `Pods/Target Support Files/Pods-bestWhiteNoise/Pods-bestWhiteNoise.debug.xcconfig'. This can lead to problems with the CocoaPods installation
    - Use the `$(inherited)` flag, or
    - Remove the build settings from the target.

[!] The `bestWhiteNoise [Release]` target overrides the `ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES` build setting defined in `Pods/Target Support Files/Pods-bestWhiteNoise/Pods-bestWhiteNoise.release.xcconfig'. This can lead to problems with the CocoaPods installation
    - Use the `$(inherited)` flag, or
    - Remove the build settings from the target.

[!] The `bestWhiteNoiseUITests [Debug]` target overrides the `ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES` build setting defined in `Pods/Target Support Files/Pods-bestWhiteNoise-bestWhiteNoiseUITests/Pods-bestWhiteNoise-bestWhiteNoiseUITests.debug.xcconfig'. This can lead to problems with the CocoaPods installation
    - Use the `$(inherited)` flag, or
    - Remove the build settings from the target.

[!] The `bestWhiteNoiseUITests [Release]` target overrides the `ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES` build setting defined in `Pods/Target Support Files/Pods-bestWhiteNoise-bestWhiteNoiseUITests/Pods-bestWhiteNoise-bestWhiteNoiseUITests.release.xcconfig'. This can lead to problems with the CocoaPods installation
    - Use the `$(inherited)` flag, or
    - Remove the build settings from the target.

查询了一些文档后,发现是我们项目中的设置 和 Pods 中的设置不一致,并且显示的是警告,实际上是错误,可能会导致你的第三方组件安装不成功等问题

解决方案

看了很多文章,都是搜索 ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES 设置成 $(inherited),但是没有细说需要设置哪几个地方,可能对于我这种新手来说就是一个坑,实际上我们需要设置每一个 TARGETS 中的 ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES$(inherited)

如图:

image

image

image

保存,然后 TARGETS 中的每一个,比如我图片中的三个,那么这三个我都需要设置

设置完后,再次运行 pod install 就好了

查看原文

赞 0 收藏 0 评论 0

enda 发布了文章 · 2020-08-07

ios 学习之基础 UI 组件 (一)

开始

你以为学完 swift 之后就可以开发 App 啦?还早呢,UI 组件学一学吧 😢

UILabel

    // 使用代码添加 UILabel 横向为 X ,纵向为 Y,坐标原点在左上角
    let label = UILabel(frame: CGRect(x: 20, y: 40, width: 200, height: 30))
    label.text = "Hello World"
    // 添加到当前视图
    self.view.addSubview(label)

    let label2 = UILabel(frame: CGRect(x: 20, y: 60, width: 200, height: 30))
    label2.text = "Geer"

    // 设置字体为 20 号加粗的系统字体
    label2.font = UIFont.boldSystemFont(ofSize: 20)

    // 设置字体颜色为红色
    label2.textColor = UIColor.red

    // 设置阴影颜色
    label2.shadowColor = UIColor.green

    // 设置阴影偏移
    label2.shadowOffset = CGSize(width: 2, height: 2)

    // 设置字体对其
    label2.textAlignment = NSTextAlignment.center
    self.view.addSubview(label2)

    // 多行文本
    let text = """
    除了自定义连接表的表名,你还可以通过传递额外的参数到 belongsToMany 方法来定义该表中字段的键名。第三个参数是定义此关联的模型在连接表里的外键名,第四个参数是另一个模型在连接表里的外键名:
    """
    let label3 = UILabel(frame: CGRect(x: 20, y: 80, width: 200, height: 150))
    label3.text = text

    // 设置显示行数
    label3.numberOfLines = 7
    self.view.addSubview(label3)

UIButton

        // 创建 button 实例,指定 button 的类型
        let button = UIButton(type: .system)
        
        // 设置位置与尺寸
        button.frame = CGRect(x: 20, y: 40, width: 100, height: 30)
        
        // 设置按钮背景颜色
        button.backgroundColor = .purple
        
        // 设置按钮标题
        button.setTitle("我是按钮", for: UIControl.State())
        
        // 设置标题背景颜色
        button.setTitleColor(.white, for: UIControl.State())
        
        // 为按钮添加事件
        // 第一个传入触发事件时事件方法的执行者,比如当前则是 self
        // 第二个参数传入一个#selector选择器实例,这个参数决定要执行的方法
        // 第三个参数设置触发的条件,列入按钮被按下,按钮被按下并抬起
        
        button.addTarget(self, action: #selector(touchBegin), for: UIControl.Event.touchUpInside)
        
        self.view.addSubview(button)
@objc func touchBegin(){
        print("click button")
    }

UIImageView

        // 创建图片实例
        let image = UIImage(named: "img1")
        
        // 创建图片 View
        let imageView = UIImageView(image: image)
        
        // 设置 view 的位置
        imageView.frame = CGRect(x: 40, y: 50, width: 200, height: 200)
        
        self.view.addSubview(imageView)
        
        // 动画
        var imageArray = Array<UIImage>()
        
        for index in 1...2 {
            if let fImage = UIImage(named: "f\(index)") {
                imageArray.append(fImage)
            }
        }
        
        // 创建 View
        let fImageView = UIImageView(frame: CGRect(x: 30, y: 250, width: 200, height: 100))
        
        // 设置动画数组
        fImageView.animationImages = imageArray
        
        // 设置播放时长
        fImageView.animationDuration = 3
        
        // 设置动画播放次数
        fImageView.animationRepeatCount = 0
        
        self.view.addSubview(fImageView)
        
        // 开始播放
        fImageView.startAnimating()

UITextField

        // 创建实例 设置尺寸
        let textField = UITextField(frame: CGRect(x: 20, y: 30, width: 100, height: 30))
        
        // 设置边框输入风格
        textField.borderStyle = .line
        
        // 设置文字颜色
        textField.textColor = .red
        
        // 设置对齐方式
        textField.textAlignment = .center
        
        // 设置提示文字
        textField.placeholder = "请输入姓名"
        
        // 设置代理为本身
        textField.delegate = self
        
        self.view.addSubview(textField)
        
        
        
        let textField2 = UITextField(frame: CGRect(x: 20, y: 90, width: 100, height: 30))
        
        // 设置边框输入风格
        textField2.borderStyle = .line
        
        // 设置文字颜色
        textField2.textColor = .red
        
        // 设置对齐方式
        textField2.textAlignment = .center
        
        // 设置提示文字
        textField2.placeholder = "请输入姓名"
        
        
        // 左视图
        let imageView1 = UIImageView(image: UIImage(named: "img1"))
        imageView1.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
        
        // 右视图
        let imageView2 = UIImageView(image: UIImage(named: "f1"))
        imageView2.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
        
        
        // 设置左右视图
        textField2.leftView = imageView1
        textField2.rightView = imageView2
        
        // 设置视图模式
        textField2.leftViewMode = .always
        textField2.rightViewMode = .always
        
        self.view.addSubview(textField2)

代理方法

// 在输入框即将进入编辑状态时调用
    func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
        print("即将进入编辑状态时调用")
        return true
    }
    
    // 已经开始编辑时调用
    func textFieldDidBeginEditing(_ textField: UITextField) {
        print("已经开始编辑时调用")
    }
    
    // 按 return 时调用
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }

UISwitch

        let swi = UISwitch()
        swi.frame = CGRect(x: 20, y: 20, width: 100, height: 20)
        
        // 设置视图中心点的坐标
        swi.center = CGPoint(x: 100, y: 100)
        
        // 设置开启状态的颜色
        swi.onTintColor = .green
        
        // 设置普通状态的颜色
        swi.tintColor = .red
        
        // 设置滑动的颜色
        swi.thumbTintColor = .purple
        
        // 设置开关的初始状态
        swi.isOn = true
        
        swi.addTarget(self, action: #selector(switchChange), for: UIControl.Event.valueChanged)
        self.view.addSubview(swi)
@objc func switchChange(swi: UISwitch){
        print(swi.isOn)
    }

UIPageController

        // 创建
        let pageControl = UIPageControl(frame: CGRect(x: 20, y: 100, width: 280, height: 30))
        
        // 设置页数
        pageControl.numberOfPages = 10
        
        // 设置背景颜色
        pageControl.backgroundColor = .red
        
        // 设置页码点背景颜色
        pageControl.pageIndicatorTintColor = .green
        
        // 设置选中的页码点颜色
        pageControl.currentPageIndicatorTintColor = .blue
        
        // 设置当前选中的页数
        pageControl.currentPage = 3
        
        pageControl.addTarget(self, action: #selector(uiPageChange), for: UIControl.Event.valueChanged)
        self.view.addSubview(pageControl)
    @objc func uiPageChange(pageControl: UIPageControl){
        print("当前 \(pageControl.currentPage)")
    }

UISegmentedControl

        let items = ["按钮1","按钮2","按钮三"]
        let segmentedControl = UISegmentedControl(items: items)
        
        // 设置位置与尺寸
        segmentedControl.frame = CGRect(x: 100, y: 100, width: 200, height: 30)
        
        // 设置控件风格与颜色
        segmentedControl.tintColor = .blue
        
        segmentedControl.addTarget(self, action: #selector(segmentedControlChange), for: UIControl.Event.valueChanged)
        
        self.view.addSubview(segmentedControl)
@objc func segmentedControlChange(seg: UISegmentedControl){
        print("选择了 \(seg.selectedSegmentIndex)")
        // 插入新的按钮
        seg.insertSegment(withTitle: "按钮5", at: 0, animated: true)
    }

UISlider

        let slider = UISlider(frame: CGRect(x: 20, y: 100, width: 280, height: 30))
        
        // 设置最小值
        slider.minimumValue = 0
        slider.maximumValue = 10
        
        // 初始滑块的值
        slider.value = 5
        
        // 设置滑块左侧进度条的颜色
        slider.minimumTrackTintColor = .red
        
        // 设置滑块右侧的颜色
        slider.maximumTrackTintColor = .green
        
        // 设置滑块的颜色
        slider.thumbTintColor = .blue
        
        // 设置停止滑动才触发事件
        slider.isContinuous = false
        
        slider.addTarget(self, action: #selector(uISliderChange), for: UIControl.Event.valueChanged)
        
        self.view.addSubview(slider)
@objc func uISliderChange(slider: UISlider){
        print(slider.value)
    }

UIActivityIndicatorView

        let activity = UIActivityIndicatorView(style: UIActivityIndicatorView.Style.medium)
        
        activity.center = self.view.center
        activity.color = .blue
        
        // 开始播放
        activity.startAnimating()
        
        self.view.addSubview(activity)

UIProgressView

        let progressView = UIProgressView(progressViewStyle: UIProgressView.Style.default)
        
        // 设置位置和宽度
        progressView.frame = CGRect(x: 20, y: 100, width: 280, height: 30)
        
        // 设置当前进度
        progressView.progress = 0.5
        
        // 设置已走过的进度条进度
        progressView.progressTintColor = .red
        
        // 设置未走过的颜色
        progressView.trackTintColor = .blue
        
        self.view.addSubview(progressView)

UIStepper

        let steper = UIStepper(frame: CGRect(x: 100, y: 100, width: 0, height: 0))
        // 设置背景颜色
        steper.backgroundColor = UIColor.red
        
        // 设置控件颜色
        
        steper.tintColor = .blue
        
        // 设置最小值
        steper.minimumValue = 0
        steper.maximumValue = 10
        
        // 设置控件的步长
        steper.stepValue = 1
        
        self.view.addSubview(steper)

UIPickerView

        let pickerView = UIPickerView(frame: CGRect(x: 20, y: 100, width: 280, height: 200))
        
        // 设置代理 需要添加 UIPickerViewDelegate
        pickerView.delegate = self
        
        // 设置数据源 需要添加 UIPickerViewDataSource
        pickerView.dataSource = self
        
        self.view.addSubview(pickerView)

代理

    // pickView 此方法需要选择器控件的分组数量
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 2
    }
    
    // 此方法需要返回每个分组的行数
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return 10
    }
    
    // 此方法返回每个分组中的每行数据的标题
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return "第\(component + 1)组第\(row)行"
    }
    
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        print("用户选择了 \(component)组\(row)行")
    }

UIDataPicker

        let dataPicker = UIDatePicker(frame: CGRect(x: 20, y: 100, width: 280, height: 200))
        
        // 设置时间选择器的模式
        dataPicker.datePickerMode = .dateAndTime
        dataPicker.addTarget(self, action: #selector(uiDataPickerChange), for: UIControl.Event.valueChanged)
        self.view.addSubview(dataPicker)
@objc func uiDataPickerChange(dataPicker: UIDatePicker){
        print(dataPicker.date)
    }

UISearchBar

let searchBar = UISearchBar(frame: CGRect(x: 20, y: 100, width: 280, height: 30))
        
        // 设置控件的风格
        searchBar.searchBarStyle = .minimal
        
        searchBar.placeholder = "请输入商品标题"
        
        // 显示取消按钮
        searchBar.showsCancelButton = true
        
        // 显示控件的书库按钮
        searchBar.showsBookmarkButton = true
        
        self.view.addSubview(searchBar)

结束

今日先学这么多,明天再继续

查看原文

赞 0 收藏 0 评论 0

enda 发布了文章 · 2020-08-03

【2020 React-Native 系列】之 react-native-splash-screen

环境

  • 撰写时间:2020-08-03
  • React Native 版本 :0.63.2
  • Xcode 版本:Version 11.6 (11E708)

在 RN 中,添加启动图是非常方便的,我们可以使用 react-native-splash-screen 来完成此工作

react-native-splash-screen 插件也有点老了,官方文档及其他教程都有一些问题,这里更新一下最新的安装过程

Install

yarn add react-native-splash-screen

ios 安装

其实只需要执行一行命令就行,会自动帮我们添加依赖包,所以官网的添加各种文件就不需要了

cd ios && pod install

等待 pod install 执行结束,由于后面 iOS 默认启动页是 LaunchScreen.storyboard,我们需要设置一下

1. 清空 Launch Screen File

image

2. 添加 LaunchImage

image

添加后,把 UI 给你的各种不同的分辨率图片往里面拖就行

3. 修改 Build Settings

搜索框搜索 Launch Image,快速定位,双击修改为 LaunchImage

image

4.修改 AppDelegate.m

AppDelegate.m 中的头部 #import "RNSplashScreen.h"

修改 AppDelegate.m 中的 didFinishLaunchingWithOptions 方法,在最后添加

[RNSplashScreen show];

image

iOS 配置结束

Android 配置

安卓也不需要添加各种包,重新 gradle sync 一下就行

1. 修改 MainActivity

路径:android/app/src/main/java/com/wendada/MainActivity.java

package com.wendada;

import com.facebook.react.ReactActivity;

# 添加下面两行
import org.devio.rn.splashscreen.SplashScreen;
import android.os.Bundle;

public class MainActivity extends ReactActivity {

  /**
   * Returns the name of the main component registered from JavaScript. This is used to schedule
   * rendering of the component.
   */
  @Override
  protected String getMainComponentName() {
    return "wendada";
  }

  // 添加下面方法
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      SplashScreen.show(this);  // here
      super.onCreate(savedInstanceState);
  }
}

2. 修改 styles.xml

路径 android/app/src/main/res/values/styles.xml

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="android:textColor">#000000</item>
        <!--添加这一行-->
        <item name="android:windowIsTranslucent">true</item>
    </style>

</resources>

3. 添加 launch_screen.xml

路径 android/app/src/main/res/layout/launch_screen.xml

添加如下内容

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:background="@drawable/launch_screen"
              android:orientation="vertical">
</LinearLayout>

4. 存放图片

把图片存放至 android/app/src/main/res/drawable/launch_screen.png

前端配置

在 App.js 中导入

import SplashScreen from 'react-native-splash-screen';

添加关闭启动图代码

componentDidMount() {
        SplashScreen.hide();
        console.log('js 关闭启动图');
    }

结束

愉快的玩耍吧

查看原文

赞 2 收藏 0 评论 2

enda 发布了文章 · 2020-08-02

【2020 React-Native 系列】之 react-native-vector-icons

环境

  • 撰写时间:2020-08-02
  • React Native 版本 :0.63.2
  • Xcode 版本:Version 11.6 (11E708)

我们在应用中,都有随处可见的小图标,那么在 React Native 中,我们一般都是通过 react-native-vector-icons 来完成此项工作

install

一行命令安装

yarn add react-native-vector-icons

IOS 平台设置

我们需要在 ios 平台下执行 pod install

 cd ios && pod install
 

然后打开我们的 xcode,源代码模式编辑 info.plist 文件

image

加入如下代码

<key>UIAppFonts</key>
  <array>
    <string>AntDesign.ttf</string>
    <string>Entypo.ttf</string>
    <string>EvilIcons.ttf</string>
    <string>Feather.ttf</string>
    <string>FontAwesome.ttf</string>
    <string>FontAwesome5_Brands.ttf</string>
    <string>FontAwesome5_Regular.ttf</string>
    <string>FontAwesome5_Solid.ttf</string>
    <string>Foundation.ttf</string>
    <string>Ionicons.ttf</string>
    <string>MaterialIcons.ttf</string>
    <string>MaterialCommunityIcons.ttf</string>
    <string>SimpleLineIcons.ttf</string>
    <string>Octicons.ttf</string>
    <string>Zocial.ttf</string>
    <string>Fontisto.ttf</string>
  </array>

然后在项目中新建 Fonts 文件夹,把 ./node_modules/react-native-vector-icons/Fonts/ 中的所有字体文件,全部拷贝进去,如图

image

重新编译运行就 ok 啦~

Android 平台设置

安卓平台设置更简单,两步即可

拷贝字体文件

首先和 iOS 一样 将 node-modeles\react-native-vector-icons\Fonts 目录下文件复制到项目andriod\app\src\main\assets\fonts 目录下,如图

image

记住,如果目录不存在就新建

修改 build.gradle 文件

文件路径:andriod/app/build.gradle ,增加如下代码


apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"

使用

安装官网文档使用即可

import Icon from 'react-native-vector-icons/FontAwesome';

<Icon name="rocket" size={30} color="#900" />

由于 RN 在国内慢慢的使用的人少了,所以很多教程文档基本上不可用,我们现在新项目正在使用 React Native,所以记录一下每一个坑,为了避免时间长久对后人造成误导,故此系列文件在开头会著名时间与版本

有任何问题,欢迎关注我公众号进行留言
image

查看原文

赞 0 收藏 0 评论 0

enda 分享了头条 · 2020-03-07

在 golang 文档中,对数组与切片有一些详细的讲解,本文主要讲解数组与切片的关系

赞 0 收藏 0 评论 0

enda 发布了文章 · 2020-03-06

一篇文章理解 golang 中切片与数组的关系

起始

在 golang 文档中,对数组与切片有一些详细的讲解,本文主要讲解数组与切片的关系

由于是个人理解,可能有些偏差,烦请指正

数组

golang 的数组比较简单,我们理解几个概念即可

  1. 数组是固定长度与容量,并且具有相同类型的一组值
  2. 此定义的数组长度为 5 ,那么容量也会固定为 5
  3. 数组的索引都是从 0 开始的

记住,我们在此定义了一个 int 类型的数组,长度容量均为 5,在后面的切片讲解中,我们将对此数组进行切片

//  此定义的数组长度为 5 ,那么容量也会固定为 5
arr := [5]int{0, 1, 2, 3, 4}
//  数组 p = 0xc00001c0f0,arr = [0 1 2 3 4],len = 5,cap = 5
fmt.Printf("数组 p = %p,arr = %+v,len = %d,cap = %d\n", &arr, arr, len(arr), cap(arr))
// 数组的索引都是从 0  开始的
// 0 1
fmt.Println(arr[0], arr[1])

切片

切片的基础概念

  1. 切片可以看做是一个可变长的数组
  2. 切片可以看做是对数组的一个片段的引用

创建切片

我们首先来创建一个对 arr 数组的一个切片

[1:3] 表示范围从数组的索引 1 至 数组的索引 3,它是不包括 3 的,可以简单理解为 index == 1 && index < 3
当切片生成后,索引默认也是从 0 开始, 切片索引是 [0,1] 对应着数组的索引是 [1,2]

arrSlice := arr[1:3]
// 切片 p = 0xc00000c060,arr = [1 2],len = 2,cap = 4
fmt.Printf("切片 p = %p,arr = %+v,len = %d,cap = %d\n", &arrSlice, arrSlice, len(arrSlice), cap(arrSlice))

修改数组,切片会发生什么?

我们上面有提到过,切片是对数组的一个引用,那么我们修改数组的值,切片会发生什么呢?

// 把数组 index = 1 的值修改为 10
arr[1] = 10

// 切片 p = 0xc00000c060,arr = [10 2],len = 2,cap = 4
fmt.Printf("切片 p = %p,arr = %+v,len = %d,cap = %d\n", &arrSlice, arrSlice, len(arrSlice), cap(arrSlice)

可以看到,我们切片对应的值也被修改为 10,切片的底层数据结构中存在的底层数组是对我们上面数组做的引用传递,关于引用传递和值传递大家应该还是分的清的

那么对应的,我们修改切片,数组也会发生相应的变化

// 同样的道理,修改切片的值也会影响到底层数组
arrSlice[0] = 8
// 切片 p = 0xc00000c060,arr = [8 2],len = 2,cap = 4
fmt.Printf("切片 p = %p,arr = %+v,len = %d,cap = %d\n", &arrSlice, arrSlice, len(arrSlice), cap(arrSlice))
// 数组 p = 0xc00001c0f0,arr = [0 8 2 3 4],len = 5,cap = 5
fmt.Printf("数组 p = %p,arr = %+v,len = %d,cap = %d\n", &arr, arr, len(arr), cap(arr))

对切片进行追加操作,会发生什么?

上面说到,我们修改切片或者是数组,都会有对应的变化,那么我们对切片进行追加呢?

// 对切片追加
arrSlice = append(arrSlice, 11)
// 切片 p = 0xc00008a020,arr = [8 2 11],len = 3,cap = 4
fmt.Printf("切片 p = %p,arr = %+v,len = %d,cap = %d\n", &arrSlice, arrSlice, len(arrSlice), cap(arrSlice))
// 数组 p = 0xc000090060,arr = [0 8 2 11 4],len = 5,cap = 5
fmt.Printf("数组 p = %p,arr = %+v,len = %d,cap = %d\n", &arr, arr, len(arr), cap(arr))

我们可以看到,数组的 index = 3 的值被修改为 11,我是这么理解的:

  1. 追加前的切片索引是 [0,1] 对应着数组的 [1,2]
  2. 在这里追加了一位,那么切片的索引是 [0,1,2] 数组对应的索引是 [1,2,3]
  3. 所以追加的值,也会修改数组的值

切片的容量?

通过上面的代码,我们可以看到我们的 cap 一直都是 4,为什么呢?这就要涉及到一个容量的计算公式了

  1. 在创建切片时,我们指定了对数组的 [1,3] 进行切片,这里切出来的长度为 2
  2. 切片在创建时,如果不指定容量,那么容量会自动去计算,我们这里没有指定容量,那么他会自动计算
  3. 创建时计算容量的公式为:创建时的长度 * 2,我们的长度是 2 ,计算出来的容量则为 4
  4. 在追加时,会先判断容量够不够,如果容量足够则容量不变;如果超出容量那么判断长度是否小于 1024 ,小于则容量 * 2,大于则容量 * 1.25

这就是为什么我们的容量一直是 4 的原因

切片容量超过原数组容量,会发生什么?

我们一直在反复提,切片是对数组的引用,那么当我切片已经超出数组的范围,会发生什么呢?

我们写代码操作一下

arrSlice = append(arrSlice, 12, 13, 14)
// 切片 p = 0xc00000c060,arr = [8 2 11 12 13 14],len = 6,cap = 8
fmt.Printf("切片 p = %p,arr = %+v,len = %d,cap = %d\n", &arrSlice, arrSlice, len(arrSlice), cap(arrSlice))
// 数组 p = 0xc00001c0f0,arr = [0 8 2 11 4],len = 5,cap = 5
fmt.Printf("数组 p = %p,arr = %+v,len = %d,cap = %d\n", &arr, arr, len(arr), cap(arr))

在上面代码中,我们追加了三个值 12,13,14

我们可以看到,数组的值并没有被修改,按照我们上一步讲的来说,应该数组的最后一位会变为 12,但是并没有
这是一个很重要的概念,当我们的切片容量大于底层数组容量时,会自动创建一个新的底层数组,取消对原数组的引用

当我们切片取消对原数组引用时,我们再去修改切片,并不会影响到原数组

arrSlice[0] = 18
// 切片 p = 0xc00008c020,arr = [18 2 11 12 13 14],len = 6,cap = 8
fmt.Printf("切片 p = %p,arr = %+v,len = %d,cap = %d\n", &arrSlice, arrSlice, len(arrSlice), cap(arrSlice))
// 数组 p = 0xc000092060,arr = [0 8 2 11 4],len = 5,cap = 5
fmt.Printf("数组 p = %p,arr = %+v,len = %d,cap = %d\n", &arr, arr, len(arr), cap(arr))

被取消引用的数组去哪了?

根据查阅资料来看,大部分人都是说当被取消引用,并且也没有别的地方去引用时,golang 的垃圾处理会自动回收;大家可以具体尝试一下

完整代码

此文章完整代码如下

// Enda <endachao@gmail.com>
package main

import "fmt"

func main() {
    //数组是固定长度与容量,并且具有相同类型的一组值
    //此定义的数组长度为 5 ,那么容量也会固定为 5
    arr := [5]int{0, 1, 2, 3, 4}
    // 数组 p = 0xc00001c0f0,arr = [0 1 2 3 4],len = 5,cap = 5
    fmt.Printf("数组 p = %p,arr = %+v,len = %d,cap = %d\n", &arr, arr, len(arr), cap(arr))
    // 数组的索引都是从 0  开始的
    // 0 1
    fmt.Println(arr[0], arr[1])

    // 切片可以看做是一个可变长的数组
    // 切片可以看做是对数组的一个片段的引用
    // [1:3] 表示范围从数组的索引 1 至 数组的索引 3,它是不包括 3 的,可以简单理解为  index == 1 && index < 3
    // 当切片生成后,索引默认也是从 0 开始, 切片索引是 [0,1] 对应着数组的索引是 [1,2]
    arrSlice := arr[1:3]
    // 切片 p = 0xc00000c060,arr = [1 2],len = 2,cap = 4
    fmt.Printf("切片 p = %p,arr = %+v,len = %d,cap = %d\n", &arrSlice, arrSlice, len(arrSlice), cap(arrSlice))

    // 由于切片是对底层数据的一个引用,所以修改底层数组会更改切片的值
    arr[1] = 10
    // 切片 p = 0xc00000c060,arr = [10 2],len = 2,cap = 4
    fmt.Printf("切片 p = %p,arr = %+v,len = %d,cap = %d\n", &arrSlice, arrSlice, len(arrSlice), cap(arrSlice))

    // 同样的道理,修改切片的值也会影响到底层数组
    arrSlice[0] = 8
    // 切片 p = 0xc00000c060,arr = [8 2],len = 2,cap = 4
    fmt.Printf("切片 p = %p,arr = %+v,len = %d,cap = %d\n", &arrSlice, arrSlice, len(arrSlice), cap(arrSlice))
    // 数组 p = 0xc00001c0f0,arr = [0 8 2 3 4],len = 5,cap = 5
    fmt.Printf("数组 p = %p,arr = %+v,len = %d,cap = %d\n", &arr, arr, len(arr), cap(arr))

    // 对切片追加
    // 追加前的切片索引是 [0,1] 对应着 数组的 [1,2]
    // 在这里追加了一位,那么切片的索引是 [0,1,2] 数组对应的索引是 [1,2,3]
    // 所以追加的值,也会修改数组的值
    arrSlice = append(arrSlice, 11)
    // 切片 p = 0xc00008a020,arr = [8 2 11],len = 3,cap = 4
    fmt.Printf("切片 p = %p,arr = %+v,len = %d,cap = %d\n", &arrSlice, arrSlice, len(arrSlice), cap(arrSlice))
    // 数组 p = 0xc000090060,arr = [0 8 2 11 4],len = 5,cap = 5
    fmt.Printf("数组 p = %p,arr = %+v,len = %d,cap = %d\n", &arr, arr, len(arr), cap(arr))

    // 切片的容量为什么是 4
    // 在创建切片时,我们指定了对数组的 [1,3] 进行切片,这里切出来的长度为 2
    // 切片在创建时,如果不指定容量,那么容量会自动去计算
    // 创建时计算容量的公式为:创建时的长度 * 2
    // 追加时,会先判断长度够不够,如果够则容量不变,如果不够那么判断长度是否小于 1024 ,小于则容量 * 2,大于则 容量 * 1.25

    // 当我们切片的长度超过了原数组的长度
    // 我们可以看到,数组的值并没有被修改,按照我们上一步讲的来说,应该数组的最后一位会变为 12,但是并没有
    // 这是一个很重要的概念,当我们的切片容量大于底层数组容量时,会自动创建一个新的底层数组
    arrSlice = append(arrSlice, 12, 13, 14)
    // 切片 p = 0xc00000c060,arr = [8 2 11 12 13 14],len = 6,cap = 8
    fmt.Printf("切片 p = %p,arr = %+v,len = %d,cap = %d\n", &arrSlice, arrSlice, len(arrSlice), cap(arrSlice))
    // 数组 p = 0xc00001c0f0,arr = [0 8 2 11 4],len = 5,cap = 5
    fmt.Printf("数组 p = %p,arr = %+v,len = %d,cap = %d\n", &arr, arr, len(arr), cap(arr))

    //当我再去修改切片的值时,并不会去操作我们上面定义的数组了
    arrSlice[0] = 18
    // 切片 p = 0xc00008c020,arr = [18 2 11 12 13 14],len = 6,cap = 8
    fmt.Printf("切片 p = %p,arr = %+v,len = %d,cap = %d\n", &arrSlice, arrSlice, len(arrSlice), cap(arrSlice))
    // 数组 p = 0xc000092060,arr = [0 8 2 11 4],len = 5,cap = 5
    fmt.Printf("数组 p = %p,arr = %+v,len = %d,cap = %d\n", &arr, arr, len(arr), cap(arr))

}
查看原文

赞 1 收藏 0 评论 0

认证与成就

  • 获得 133 次点赞
  • 获得 7 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 7 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

注册于 2013-10-22
个人主页被 2.4k 人浏览