golangのv1.16の開発環境を準備する
いつの間にか
v.1.16まで上がっていた、なんか以前とパッケージの扱い? とか変わっているので少し見直し
なんかgo modulesとかいうのがあるらしい
当時は各モジュールの最新バージョンが適用されやすくなっていて 新しい環境でビルドした際にコンパイルエラーとなっていたことがある。 多分、revelとか・・・
そのため、バージョンを固定にして対応していた このgo modulesを使用するとバージョンを各プロジェクト毎に管理できるらしく、 ちょっと楽になるらしい
参考情報
ローカル環境のみでの Go Modules と自作パッケージ - Qiita
WindowsにGo言語開発環境をインストールする - Qiita
goの再インストールから
インストール
% brew install go % go version go version go1.16.3 darwin/amd64 %
GOPATH設定
srcは管理されなくなったような気がするが、pkgとbinは使われているみたい
GOPATH用準備
% mkdir -p $HOME/work/go/{src,pkg,bin} % export GOPATH=$HOME/work/go
サンプルプロジェクト
ディレクトリ作成
% mkdir -p $HOME/work/golang/sample1 % cd $HOME/work/golang/sample1
go modules初期化
% go mod init sample1 go: creating new go.mod: module sample1 %
※モジュール名はローカルならプロジェクト名で良い、githubmなどに公開する場合はgithub/xxxxとかにしないといけない
go.modの中身
% cat go.mod module sample1 go 1.16 %
なんかパッケージを入れてみる
% go get github.com/labstack/echo/v4 go: downloading github.com/labstack/echo v1.4.4 go: downloading github.com/labstack/echo/v4 v4.2.2 go: downloading github.com/labstack/echo v3.3.10+incompatible go: downloading github.com/labstack/gommon v0.3.0 go: downloading golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a go: downloading golang.org/x/net v0.0.0-20200822124328-c89045814202 go: downloading github.com/mattn/go-colorable v0.1.7 go: downloading github.com/mattn/go-isatty v0.0.12 go: downloading github.com/valyala/fasttemplate v1.2.1 go: downloading golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6 go: downloading github.com/valyala/bytebufferpool v1.0.0 go: downloading golang.org/x/text v0.3.3 go get: added github.com/labstack/echo/v4 v4.2.2 %
↓
% cat go.mod module sample1 go 1.16 require github.com/labstack/echo/v4 v4.2.2 // indirect %
直接、go.modに編集しても良いらしい
サンプルコード
sample1.go
package main import ( "fmt" echo "github.com/labstack/echo/v4" "sample1/src/car" ) func main() { fmt.Println("aaa") fmt.Println(echo.Version) a := new(car.Car) a.Init() a.Msg() }
src/car/car.go
package car import "fmt" type Car struct { name string } func (p *Car) Msg() { fmt.Println(p.name) } func (p *Car) Init() { p.name = "くるま" }
以前はローカル環境の場合は相対パスでも動いていた気がしますが、 go modulesの場合はNGになったかもしれない
ディレクトリ構成
% tree . ├── go.mod ├── go.sum ├── sample1.go ├── src ├ └── car ├ └── car.go └── workspace.code-workspace
おまけ
vscode設定(setting.json)
"settings": { "go.gopath": "/Users/xxxx/work/go", ⇦ GOPATHの場所 "go.formatOnSave": true, "go.goroot": "/usr/local/Cellar/go/1.16.3/libexec" ⇦ GOROOTの場所 }
初回にデバッグ用ツールが入っていない場合はインストールするので定義した方が良い goparthを定義しないとデフォルトのGOPATHの場所になるので注意
react-native-configで環境変数を参照する3(android編)
前回
今回やること
前回って環境変数を読むのにENVFILEとか設定していましたよね? あれだけではビルド時のアプリ名とか各環境のアプリ名などの調整が困難なので その辺の設定周り
補足
flavorとか利用しますが、厳密に理解はしていないため、 今回はこの設定でできたようなものとなります
参考
ReactNative製アプリのリリースTips(Android編) | スペースマーケットブログ
ReactNativeのAndroid側でFlavorで環境を切り分ける - Qiita
ReactNative(Android)でビルドバリアント毎にapk出力(署名つき) - Qiita
ReactNative 0.60.4、react-native-config を使って環境構築、リリースまで1 - LOCAL-C BLOG
【ReactNative】Androidリリースビルド時のメモ(2019/10/28 追記あり) - Qiita
react-nativeで初めてのnativeアプリリリース(android編)│tech1000+
【ReactNative】Androidリリースをイチからメモ - メモメモメモ
flavorを利用します
android/app/build.gradleへの設定1:defaultConfigにbuild_config_packageの設定を追加
defaultConfig { applicationId "com.sampleconfig01" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode 1 versionName "1.0" // 追加 resValue "string", "build_config_package", "com.sampleconfig01" }
android/app/build.gradleへの設定2:signingConfigsにrelease用の設定を追加
signingConfigs { debug { storeFile file('debug.keystore') storePassword 'android' keyAlias 'androiddebugkey' keyPassword 'android' } // 任意のキーストアファイルを利用 release { if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) { storeFile file(MYAPP_RELEASE_STORE_FILE) storePassword MYAPP_RELEASE_STORE_PASSWORD keyAlias MYAPP_RELEASE_KEY_ALIAS keyPassword MYAPP_RELEASE_KEY_PASSWORD } } }
android/app/build.gradleへの設定3:buildTypesにrelease用の設定を追加
buildTypes { debug { signingConfig signingConfigs.debug } release { // Caution! In production, you need to generate your own keystore file. // see https://reactnative.dev/docs/signed-apk-android. signingConfig signingConfigs.release minifyEnabled enableProguardInReleaseBuilds proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" } }
android/app/build.gradleへの設定4:flavorの設定を追加
// applicationVariants are e.g. debug, release applicationVariants.all { variant -> variant.outputs.each { output -> // For each separate APK per architecture, set a unique version code as described here: // https://developer.android.com/studio/build/configure-apk-splits.html // Example: versionCode 1 will generate 1001 for armeabi-v7a, 1002 for x86, etc. def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] def abi = output.getFilter(OutputFile.ABI) if (abi != null) { // null for the universal-debug, universal-release variants output.versionCodeOverride = defaultConfig.versionCode * 1000 + versionCodes.get(abi) } } } // flavor追加 flavorDimensions "default" productFlavors { dev { versionName = android.defaultConfig.versionName + '-dev' applicationIdSuffix ".dev" } stg { versionName = android.defaultConfig.versionName + '-staging' applicationIdSuffix ".stg" } prd { versionName = android.defaultConfig.versionName } } } dependencies { ・ ・ ・
android/gradle.propertiesにrelease用のキーストアの設定を追加
今回はセキュリティ的な面も含めてデバッグ時のものをコピー
# releaseキーストア設定 MYAPP_RELEASE_STORE_FILE=release.keystore MYAPP_RELEASE_KEY_ALIAS=androiddebugkey MYAPP_RELEASE_STORE_PASSWORD=android MYAPP_RELEASE_KEY_PASSWORD=android
アプリのアイコン名などを環境別に作成
android/app/src配下のディレクトリに以下の構成を追加
※mainやdebugなどはそのままで削除しなくて良い
android/app/src ├── dev │ └── res │ └── values │ └── strings.xml ├── prd │ └── res │ └── values │ └── strings.xml └── stg └── res └── values └── strings.xml
android/app/src/dev/res/values/strings.xml
<resources> <string name="app_name">アプリ開発</string> </resources>
android/app/src/stg/res/values/strings.xml
<resources> <string name="app_name">アプリ受入</string> </resources>
android/app/src/prd/res/values/strings.xml
<resources> <string name="app_name">アプリ本番</string> </resources>
とりあえず設定は完了
実行
開発用
npx react-native run-android --variant=DevDebug --appIdSuffix dev
検証用
npx react-native run-android --variant=StgDebug --appIdSuffix stg
本番用
npx react-native run-android --variant=PrdDebug
↓
本番用ビルド
デバッグ時はデバッグアプリとして動作するため、実行時のマシンとデバッグ監視サーバとかが動作し、 また、スマホから実行する際もhttp系で証明書なしでも通信が可能となる
assetsディレクトリ準備
作成されていない場合は作成しておく
android/app/src/main/assets
バンドル作成
npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest --assets-dest android/app/build/intermediates/res/merged/release/
アプリ作成
cd android ./gradlew assembleDev ./gradlew assembleStg ./gradlew assemblePrd
作成場所
% tree app/build/outputs/apk/ app/build/outputs/apk/ ├── debug │ ├── app-debug.apk │ └── output-metadata.json ├── dev │ ├── debug │ │ ├── app-dev-debug.apk │ │ └── output-metadata.json │ └── release │ ├── app-dev-release.apk │ └── output-metadata.json ├── prd │ └── debug │ ├── app-prd-debug.apk │ └── output-metadata.json └── stg └── debug ├── app-stg-debug.apk └── output-metadata.json
アプリインストール
adb [-s デバイスID] install app/build/outputs/apk/dev/release/app-dev-release.apk
※apkファイルは環境に合わせて読み替える ※デバイスID未指定の場合は有効なデバイス全てにインストールする
package.json改修
"scripts": { "android": "react-native run-android --variant=DevDebug --appIdSuffix dev", "android_dev": "react-native run-android --variant=DevDebug --appIdSuffix dev", "android_stg": "react-native run-android --variant=StgDebug --appIdSuffix stg", "android_prd": "react-native run-android --variant=PrdDebug", "android_bundle": "react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest --assets-dest android/app/build/intermediates/res/merged/release/", "android_release": "yarn android_bundle && cd android && ./gradlew assembleDev && ./gradlew assembleStg && ./gradlew assemblePrd", "ios": "react-native run-ios", "ios_dev": "echo '.env' > /tmp/envfile && yarn ios", "ios_stg": "echo '.env.staging' > /tmp/envfile && yarn ios", "ios_prd": "echo '.env.production' > /tmp/envfile && yarn ios", "start": "react-native start", "test": "jest", "lint": "eslint ." },
react-native-configで環境変数を参照する2
前回の続き
今回やること
環境別のファイルを作成して、それぞれのファイルで読み込むようにする
環境別ファイルを作成する
.env
MODE=dev APP_NAME=TEST VERSION=0.0.1
.env.staging
MODE=staging APP_NAME=STAGING VERSION=0.0.1
.env.production
MODE=production APP_NAME=RELEASE VERSION=0.0.1
簡単な実行方法
android
シェル変数の「ENVFILE」に環境変数ファイルを設定することで対応可能 またはENVFILEを環境変数名(export)化しても良い
ENVFILE=.env yarn android または ENVFILE=.env.staging yarn android または ENVFILE=.env.production yarn android
ios
「/tmp/envfile」に環境変数ファイルを設定することで対応可能 またはENVFILEを環境変数名(export)化しても良い
echo '.env' > /tmp/envfile && yarn ios または echo '.env.staging' > /tmp/envfile && yarn ios または echo '.env.production' > /tmp/envfile && yarn ios
※iosを実機で動作させる場合はyarnコマンドではなく、Xcodeで動作させることになるため、別途対応が必要
package.json設定
簡略化したコマンドを作成
"scripts": { "android": "react-native run-android", "android_dev": "ENVFILE=.env yarn android", "android_stg": "ENVFILE=.env.staging yarn android", "android_prd": "ENVFILE=.env.production yarn android", "ios": "react-native run-ios", "ios_dev": "echo '.env' > /tmp/envfile && yarn ios", "ios_stg": "echo '.env.staging' > /tmp/envfile && yarn ios", "ios_prd": "echo '.env.production' > /tmp/envfile && yarn ios", "start": "react-native start", "test": "jest", "lint": "eslint ." },
補足
androidやiosのリリース用時のセットアップ方法などはちょっと複雑なので次回以降にする androidの場合はbuildTypesとかproductFlavorsとかいじることになりそう iosはXCode主体で対応する
react-native-configで環境変数を参照する
react-native-config
1つのプロジェクトで開発、検証、本番などを行う際、 それぞれ別のプロジェクトで運用するのはたいへんなため、環境変数などで APIの向き先などを調整する
今回やること
react-native-configで環境変数を参照するところまで
参考情報
GitHub - luggit/react-native-config: Bring some 12 factor love to your mobile apps!
GitHub - Clintal/react-native-config at ios-manual-linking
react-nativeで環境ごとに定数を切り替える(react-native-config) | I am mitsuruog
ReactNativeConfig使ってみた&使い方 - Qiita
React Nativeにおける環境別ビルド設定 | エンジニアブログ | 株式会社スクーラー
手順
プロジェクトを作成
npx react-native init sampleConfig01 cd sampleConfig01
react-native-configを導入
yarn add react-native-config
pod install(iosのみ実施)
npx pod-install
手動設定(android)
/android/settings.gradleにreact-native-configを追加
rootProject.name = 'sampleConfig01' apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) include ':app' // react-native-config用追加 include ':react-native-config' project(':react-native-config').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-config/android')
/android/app/build.gradleにreact-native-configを追加
dependencies { implementation fileTree(dir: "libs", include: ["*.jar"]) //noinspection GradleDynamicVersion implementation "com.facebook.react:react-native:+" // From node_modules // react-native-condig用追加 implementation project(':react-native-config') ・ ・ ・ }
/android/app/build.gradleの先頭から2行目あたりに以下を追加
project.ext.envConfigFiles = [ debug: ".env", dev: ".env.dev", stg: ".env.staging", prd: ".env.production", anycustombuildlowercase: ".env", ] apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"
手動設定(ios)
workspaceを開く
node_modules配下のreact-native-configのプロジェクトをドラッグして参照を紐付ける
一旦、ビルドを行う
プロジェクトのpod配下にコンパイルされたreact-native-configのモジュールを紐付け
再度、ビルドを行う
.envファイルを作成
.env
APP_NAME=TEST VERSION=0.0.1
react-nativeへ実装
App.js
/** * Sample React Native App * https://github.com/facebook/react-native * * @format * @flow strict-local */ import React from 'react'; import {Text, View} from 'react-native'; import Config from 'react-native-config'; const App = () => { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', }}> <Text>APP_NAME: {Config.APP_NAME}</Text> <Text>VERSION: {Config.VERSION}</Text> </View> ); }; export default App;
結果
補足
自動リンクではファイルからデータを取得できなかったため、手動で設定して取得するように対応 環境別の指定方法とかは今度かく
続き
AWSのLambdaとAPIGatwwayを連携
作りたいもの
要約
なんか簡単な処理をAPIを経由してアクセスしたい
↓
lambdaでなんかできそう
↓
postmanで再現するにはホストがいる
↓
API Gatewayでいけそう⇦今ここ
↓
多分、APIGateway+Lambdaの連携でできるかも
lambdaは色々なAWSサービスのトリガーで動作することができる
やること
1. APIGatewayを作成
↓
↓
↓
2. APIのリソースを作成
↓
↓
3. APIのメソッドを作成
↓ ↓
4. lambdaを作成
↓
↓
↓
添付コード
exports.handler = async (event, context, callback) => { console.log("EVENT: \n" + JSON.stringify(event, null, 2)) // リクエスト console.log("body: ", event.body); // レスポンス const response = { statusCode: 200, headers: { "Content-Type": "application/json" }, body: JSON.stringify({ "aaa": 111, "bbb": "aaa", }), }; callback(null, response); };
↓
5. APIとLambdaを紐付けデプロイ
↓
↓
↓
↓
↓
6. curlで確認
% curl https://5ftyywmhe6.execute-api.ap-northeast-1.amazonaws.com/dev/test1 {"aaa":111,"bbb":"aaa"}% %
できた ^_^
おまけ
lambdaからみたAPI Gatewayからのeventの中身
{ "resource": "/test1", "path": "/test1", "httpMethod": "GET", "headers": { "Accept": "*/*", "CloudFront-Forwarded-Proto": "https", "CloudFront-Is-Desktop-Viewer": "true", "CloudFront-Is-Mobile-Viewer": "false", "CloudFront-Is-SmartTV-Viewer": "false", "CloudFront-Is-Tablet-Viewer": "false", "CloudFront-Viewer-Country": "JP", "Host": "一応隠す", "User-Agent": "curl/7.64.1", "Via": "一応隠す", "X-Amz-Cf-Id": "一応隠す", "X-Amzn-Trace-Id": "一応隠す", "X-Forwarded-For": "一応隠す", "X-Forwarded-Port": "443", "X-Forwarded-Proto": "https" }, "multiValueHeaders": { "Accept": [ "*/*" ], "CloudFront-Forwarded-Proto": [ "https" ], "CloudFront-Is-Desktop-Viewer": [ "true" ], "CloudFront-Is-Mobile-Viewer": [ "false" ], "CloudFront-Is-SmartTV-Viewer": [ "false" ], "CloudFront-Is-Tablet-Viewer": [ "false" ], "CloudFront-Viewer-Country": [ "JP" ], "Host": [ "一応隠す" ], "User-Agent": [ "curl/7.64.1" ], "Via": [ "一応隠す" ], "X-Amz-Cf-Id": [ "一応隠す" ], "X-Amzn-Trace-Id": [ "一応隠す" ], "X-Forwarded-For": [ "一応隠す" ], "X-Forwarded-Port": [ "443" ], "X-Forwarded-Proto": [ "https" ] }, "queryStringParameters": null, "multiValueQueryStringParameters": null, "pathParameters": null, "stageVariables": null, "requestContext": { "resourceId": "一応隠す", "resourcePath": "/test1", "httpMethod": "GET", "extendedRequestId": "一応隠す", "requestTime": "30/Dec/2020:06:47:19 +0000", "path": "/dev/test1", "accountId": "一応隠す", "protocol": "HTTP/1.1", "stage": "dev", "domainPrefix": "一応隠す", "requestTimeEpoch": 一応隠す, "requestId": "一応隠す", "identity": { "cognitoIdentityPoolId": null, "accountId": null, "cognitoIdentityId": null, "caller": null, "sourceIp": "一応隠す", "principalOrgId": null, "accessKey": null, "cognitoAuthenticationType": null, "cognitoAuthenticationProvider": null, "userArn": null, "userAgent": "curl/7.64.1", "user": null }, "domainName": "一応隠す", "apiId": "一応隠す" }, "body": null, "isBase64Encoded": false }
リクエストパラメータ
GETの場合は「queryStringParameters」とかに、POSTの場合は「body」に入るみたい
"queryStringParameters": null, "multiValueQueryStringParameters": null, "body": null,
Lambda単体で動作検証したい場合はここにパラメータ突っ込めば良いかな・・・
次に作りたいもの
とりあえず、 S3にファイルが置かれたら起動するやつとか作ってみたい
react-nativeでタブナビゲーションを実装
作成したやつ
参考情報
React Navigationのタブナビゲーションをカスタマイズしてみよう! - bagelee(ベーグリー) createMaterialTopTabNavigator | React Navigation
github
react-native_samples/sampleAppNavigation01 at main · mshige1979/react-native_samples · GitHub
コード全体
/** * Sample React Native App * https://github.com/facebook/react-native * * @format * @flow strict-local */ import React, {useState} from 'react'; import {View, StyleSheet, StatusBar, Platform} from 'react-native'; import {NavigationContainer} from '@react-navigation/native'; import {createMaterialTopTabNavigator} from '@react-navigation/material-top-tabs'; // タブエリア import AppTabBar from './src/components/AppTabBar'; // サンプルページ import Home from './src/screens/home'; import Profile from './src/screens/profile'; import MyPage from './src/screens/mypage'; // タブコンポーネント const TopTabs = createMaterialTopTabNavigator(); const TopTabsScreen = () => { const [swipeEnabled, setSwipeEnabled] = useState(true); // Profileの場合は左右にスワイプする // Profile以外の場合はスワイプしない // 参考:https://stackoverflow.com/questions/63611393/react-native-material-top-tab-navigator-swipe-disable-depending-on-screens const focusCheck = ({navigation, route}) => ({ focus: () => { console.log('focus: ', route.name); setSwipeEnabled(route.name === 'Profile'); }, }); return ( <TopTabs.Navigator swipeEnabled={swipeEnabled} // スワイプによる移動を制御(true: スワイプ移動、false: 移動しない) tabBar={(props) => <AppTabBar {...props} />} style={{ marginTop: Platform.select({ ios: 50, android: 0, }), }}> <TopTabs.Screen name="Home" component={Home} listeners={focusCheck} /> <TopTabs.Screen name="Profile" component={Profile} listeners={focusCheck} /> <TopTabs.Screen name="MyPage" component={MyPage} listeners={focusCheck} /> </TopTabs.Navigator> ); }; // メイン const App = () => { return ( <> <NavigationContainer> <TopTabsScreen /> </NavigationContainer> <StatusBar barStyle="dark-content" /> </> ); }; const styles = StyleSheet.create({}); export default App;
1.画面を作成
import React, {useEffect} from 'react'; import {View, Text, StyleSheet, Button} from 'react-native'; const Home = ({navigation, route}) => { return ( <View style={styles.container}> <View> <Text>Home</Text> </View> <View style={{ margin: 10, }}> <Text>Topタブのサンプル このタブはスワイプしない</Text> </View> <View> <Button title="Profileへ移動" onPress={() => { navigation.jumpTo('Profile'); }} /> </View> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, }); export default Home;
こーいうものを作成する
2. タブコンポーネントを作成
1で作成したコンポーネントを設定する。 基本2〜5位がちょうどいい感じ
// タブコンポーネント const TopTabs = createMaterialTopTabNavigator(); const TopTabsScreen = () => { const [swipeEnabled, setSwipeEnabled] = useState(true); // Profileの場合は左右にスワイプする // Profile以外の場合はスワイプしない // 参考:https://stackoverflow.com/questions/63611393/react-native-material-top-tab-navigator-swipe-disable-depending-on-screens const focusCheck = ({navigation, route}) => ({ focus: () => { console.log('focus: ', route.name); setSwipeEnabled(route.name === 'Profile'); }, }); return ( <TopTabs.Navigator swipeEnabled={swipeEnabled} // スワイプによる移動を制御(true: スワイプ移動、false: 移動しない) tabBar={(props) => <AppTabBar {...props} />} style={{ marginTop: Platform.select({ ios: 50, android: 0, }), }}> <TopTabs.Screen name="Home" component={Home} listeners={focusCheck} /> <TopTabs.Screen name="Profile" component={Profile} listeners={focusCheck} /> <TopTabs.Screen name="MyPage" component={MyPage} listeners={focusCheck} /> </TopTabs.Navigator> ); };
swipeEnabled
⇨ 左右にスワイプするための設定値、trueでスワイプする、falseでしない
フォーカスイベントで任意の画面のみスワイプするように制御可能
// Profileの場合は左右にスワイプする // Profile以外の場合はスワイプしない // 参考:https://stackoverflow.com/questions/63611393/react-native-material-top-tab-navigator-swipe-disable-depending-on-screens const focusCheck = ({navigation, route}) => ({ focus: () => { console.log('focus: ', route.name); setSwipeEnabled(route.name === 'Profile'); }, });
3.メイン画面に組み込む
// メイン const App = () => { return ( <> <NavigationContainer> <TopTabsScreen /> </NavigationContainer> <StatusBar barStyle="dark-content" /> </> ); };
おまけ
独自タブバー
標準でスタイルが適用されているが、一部独自に組み込みたい場合
import React from 'react'; import {View, Text, TouchableOpacity} from 'react-native'; import Animated from 'react-native-reanimated'; // 独自タブ // 参考:https://bagelee.com/programming/react-native/react-navigation-customize/ // 参考:https://reactnavigation.org/docs/material-top-tab-navigator const AppTabBar = ({state, descriptors, navigation, position}) => { const {routes, index} = state; const { containerStyle, tabStyle, selectedTabStyle, textStyle, selectedTextStyle, } = styles; //console.log(position); //console.log(descriptors); return ( <View style={containerStyle}> {routes.map((route, idx) => { //const inputRange = state.routes.map((_, i) => i); //console.log(inputRange); // 選択しているタブ if (index === idx) { return ( <View key={idx} style={[tabStyle, selectedTabStyle]}> <Text style={[textStyle, selectedTextStyle]}> {routes[idx].name} </Text> </View> ); } // 他のタブ return ( <TouchableOpacity style={tabStyle} key={idx} onPress={() => { // タップしたら他のタブへ切り替え navigation.navigate(route.name); }}> <Animated.Text style={[textStyle]}> {routes[idx].name} </Animated.Text> </TouchableOpacity> ); })} </View> ); }; const styles = { containerStyle: { //paddingTop: 30, borderBottomWidth: 3, borderBottomColor: '#5ab4bd', display: 'flex', flexDirection: 'row', justifyContent: 'space-between', backgroundColor: '#fcf6d6', }, tabStyle: { flex: 1, //marginRight: 1, //marginLeft: 1, height: 40, //borderTopLeftRadius: 16, //borderTopRightRadius: 16, backgroundColor: '#ffffff', }, selectedTabStyle: { backgroundColor: '#5ab4bd', }, textStyle: { fontWeight: 'bold', textAlign: 'center', paddingTop: 14, }, selectedTextStyle: { color: '#ffffff', }, }; export default AppTabBar;
とりあえず、ここまでにしておく・・・
react-nativeでモーダル表示
react-nativeでモーダル表示
作成したもの
ソースコード
/** * Sample React Native App * https://github.com/facebook/react-native * * @format * @flow strict-local */ import React, {useState} from 'react'; import { SafeAreaView, StyleSheet, Button, View, Text, StatusBar, Modal, Alert, TouchableOpacity, Image, Dimensions, } from 'react-native'; const height = Dimensions.get('window').height; const width = Dimensions.get('window').width; const App = () => { const [modalVisible, setModalVisible] = useState(false); console.log(height); console.log(width); return ( <> <StatusBar barStyle="dark-content" /> <SafeAreaView> <Button title="モーダルを開く" onPress={() => { setModalVisible(true); }} /> <Modal animationType="slide" transparent={true} visible={modalVisible} //onRequestClose={() => { // Alert.alert('Modal has been closed.'); //}} > <TouchableOpacity activeOpacity={1} style={[styles.centeredView]} onPress={(event) => { console.log('おや'); setModalVisible(false); }}></TouchableOpacity> <View style={[styles.modalView]}> <Text>sample</Text> <Image source={require('./assets/img/kaisya_woman_bad.png')} style={{ width: width * 0.4, height: 200, //borderWidth: 1, borderColor: '#000000', }} resizeMode="contain" /> <Button title="閉じる" onPress={() => { console.log('こ'); setModalVisible(false); }} /> </View> </Modal> </SafeAreaView> </> ); }; const styles = StyleSheet.create({ centeredView: { flex: 1, justifyContent: 'center', alignItems: 'center', //marginTop: 22, backgroundColor: '#CCC', opacity: 0.7, }, modalView: { position: 'absolute', alignSelf: 'center', top: height / 5, margin: 20, backgroundColor: 'white', borderRadius: 20, padding: 35, alignItems: 'center', shadowColor: '#000', shadowOffset: { width: 0, height: 2, }, shadowOpacity: 0.25, shadowRadius: 3.84, elevation: 5, }, }); export default App;
使い方
モーダルコンポーネントを画面のどこかに配置とし、propのvisible
をfalseの状態にしておく
<Modal animationType="slide" transparent={true} visible={modalVisible} //onRequestClose={() => { // Alert.alert('Modal has been closed.'); //}} > <TouchableOpacity activeOpacity={1} style={[styles.centeredView]} onPress={(event) => { console.log('おや'); setModalVisible(false); }}></TouchableOpacity> <View style={[styles.modalView]}> <Text>sample</Text> <Image source={require('./assets/img/kaisya_woman_bad.png')} style={{ width: width * 0.4, height: 200, //borderWidth: 1, borderColor: '#000000', }} resizeMode="contain" /> <Button title="閉じる" onPress={() => { console.log('こ'); setModalVisible(false); }} /> </View> </Modal>
Buttonコンポーネントなどのタップイベントで展開開くようにする
<Button title="モーダルを開く" onPress={() => { setModalVisible(true); }} />
まあ、ボタン出なくても条件を満たして値をtrueにすれば良い