9 |
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
--------------------------------------------------------------------------------
/src/demo/ReactNativeUIDemo/demos/ReactNativeUIImage.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import { View, Image } from 'react-native';
3 |
4 | export default () => {
5 | console.log("maxieeee :" + JSON.stringify(Image.getSize('react_native')))
6 |
7 | return
8 |
16 |
17 | }
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @format
3 | */
4 | import React from "react";
5 | import {AppRegistry, YellowBox} from 'react-native';
6 | import App from './src/pages/home';
7 | import {name as appName} from './app.json';
8 | import { Provider } from 'react-redux'
9 | import store from './src/config/store';
10 |
11 |
12 | YellowBox.ignoreWarnings([
13 | 'Require cycle:',
14 | ]);
15 |
16 | class ConnectedApp extends React.Component {
17 | render() {
18 | return
19 |
20 |
21 | }
22 | }
23 |
24 | AppRegistry.registerComponent(appName, () => ConnectedApp);
25 |
--------------------------------------------------------------------------------
/src/widgets/tab/bottom/TabBarItem.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { Image } from 'react-native';
3 |
4 | export default class TabBarItem extends Component {
5 | render() {
6 | let selectedImage = this.props.selectedImage ?
7 | this.props.selectedImage : this.props.normalImage;
8 | return (
9 |
16 | )
17 | }
18 | }
--------------------------------------------------------------------------------
/android/app/build_defs.bzl:
--------------------------------------------------------------------------------
1 | """Helper definitions to glob .aar and .jar targets"""
2 |
3 | def create_aar_targets(aarfiles):
4 | for aarfile in aarfiles:
5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")]
6 | lib_deps.append(":" + name)
7 | android_prebuilt_aar(
8 | name = name,
9 | aar = aarfile,
10 | )
11 |
12 | def create_jar_targets(jarfiles):
13 | for jarfile in jarfiles:
14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")]
15 | lib_deps.append(":" + name)
16 | prebuilt_jar(
17 | name = name,
18 | binary_jar = jarfile,
19 | )
20 |
--------------------------------------------------------------------------------
/ios/MaxieeRNLab/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | }
33 | ],
34 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
--------------------------------------------------------------------------------
/ios/MaxieeRNLabTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/demo/NavigationDemo/CustomHeader/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { View, Text, Button } from 'react-native';
3 |
4 | class HeaderComp extends React.Component {
5 | render() {
6 | console.log(this.props)
7 | return (
8 |
11 | {this.props.title} with CustomHeader
12 |
13 | )
14 | }
15 | }
16 |
17 | export default class CustomHeader extends React.Component {
18 | static navigationOptions = {
19 | headerTitle: ,
20 | title: 'CustomHeaderPage' // 无效
21 | }
22 |
23 | constructor(props) {
24 | super(props);
25 |
26 | }
27 |
28 | render() {
29 | return CustomHeader
30 | }
31 | }
--------------------------------------------------------------------------------
/src/widgets/gridview/GridView.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { View, Text, StyleSheet } from 'react-native'
3 | import screen from '../../common/screen';
4 | import GridItem from './GridItem';
5 |
6 | export default (props) => {
7 | return (
8 |
9 | {props.infos.map((info, index) => (
10 | props.onGridSelected(index)} />
14 | ))}
15 |
16 | )
17 | }
18 |
19 | const styles = StyleSheet.create({
20 | container: {
21 | flexDirection: 'row',
22 | flexWrap: 'wrap',
23 | justifyContent: 'space-between',
24 | borderTopWidth: screen.onePixel,
25 | borderLeftWidth: screen.onePixel,
26 | borderColor: '#e0e0e0'
27 | },
28 | })
--------------------------------------------------------------------------------
/ios/MaxieeRNLab-tvOSTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/demo/NavigationDemo/NavigationHello/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { View } from 'react-native'
3 | import Markdown from "react-native-markdown-renderer";
4 | import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs'
5 | import DocHelloNavigation from "../doc/DocHelloNavigation";
6 |
7 | let DocComp = () =>
8 | {DocHelloNavigation}
9 |
10 |
11 | let CodeComp = () =>
12 |
13 | const Tab = createMaterialTopTabNavigator();
14 |
15 | export default () => {
16 | return (
17 |
18 |
21 |
24 |
25 | )
26 | }
27 |
--------------------------------------------------------------------------------
/src/pages/basic/RNScrollableTabView.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { View } from 'react-native';
3 | import { Heading2 } from '../../widgets/text/Text';
4 | import ScrollableTabView from 'react-native-scrollable-tab-view';
5 | import screen from '../../common/screen';
6 |
7 | const SimpleTab = () =>
8 |
9 |
10 |
11 |
12 |
13 | export default (props) => {
14 | return (
15 |
16 | Simple
17 |
18 |
19 | )
20 | }
--------------------------------------------------------------------------------
/android/app/src/main/java/com/maxieernlab/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.maxieernlab;
2 |
3 | import com.facebook.react.ReactActivity;
4 | import com.facebook.react.ReactActivityDelegate;
5 | import com.facebook.react.ReactRootView;
6 | import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
7 |
8 | public class MainActivity extends ReactActivity {
9 |
10 | /**
11 | * Returns the name of the main component registered from JavaScript.
12 | * This is used to schedule rendering of the component.
13 | */
14 | @Override
15 | protected String getMainComponentName() {
16 | return "MaxieeRNLab";
17 | }
18 |
19 | @Override
20 | protected ReactActivityDelegate createReactActivityDelegate() {
21 | return new ReactActivityDelegate(this, getMainComponentName()) {
22 | @Override
23 | protected ReactRootView createRootView() {
24 | return new RNGestureHandlerEnabledRootView(MainActivity.this);
25 | }
26 | };
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 | android.useAndroidX=true
20 | # Automatically convert third-party libraries to use AndroidX
21 | android.enableJetifier=true
--------------------------------------------------------------------------------
/src/demo/ReactNativeUIDemo/buttons/GradientButton.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import LinearGradient from 'react-native-linear-gradient';
3 | import { TouchableOpacity, Text, StyleSheet } from 'react-native';
4 |
5 | export default ({text, style, ...props}) =>
8 |
13 | { text }
14 |
15 |
16 |
17 | const styles = StyleSheet.create({
18 | LinearGradientStyle: {
19 | height: 48,
20 | paddingLeft: 15,
21 | paddingRight: 15,
22 | borderRadius: 5,
23 | marginBottom: 20,
24 | alignItems: 'center',
25 | justifyContent: 'center'
26 | },
27 | buttonText: {
28 | fontSize: 18,
29 | textAlign: 'center',
30 | margin: 7,
31 | color : '#fff',
32 | backgroundColor: 'transparent'
33 | },
34 | });
--------------------------------------------------------------------------------
/src/reducers/todo/reducer.js:
--------------------------------------------------------------------------------
1 | import { ACTION_TODO_ADD, ACTION_TODO_FINISH, ACTION_TODO_UNFINISH } from "../../config/actions";
2 |
3 | const initialState = {
4 | todos: []
5 | }
6 |
7 | let toggleTodoFromTodos = (todos, id, status) => todos.map(v => {
8 | if (v.id !== id) {
9 | return v;
10 | }
11 | return {
12 | ...v,
13 | finished: status
14 | }
15 | })
16 |
17 | const todoReducer = (state = initialState, { type, payload }) => {
18 | switch (type) {
19 | case ACTION_TODO_ADD:
20 | return {
21 | ...state,
22 | todos: [...state.todos, payload]
23 | }
24 | case ACTION_TODO_FINISH:
25 | return {
26 | ...state,
27 | todos: toggleTodoFromTodos(state.todos, payload, true)
28 | }
29 | case ACTION_TODO_UNFINISH:
30 | return {
31 | ...state,
32 | todos: toggleTodoFromTodos(state.todos, payload, false)
33 | }
34 | default:
35 | return state
36 | }
37 | }
38 |
39 | export default todoReducer
--------------------------------------------------------------------------------
/src/widgets/navi/NavigationItem.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Image, Text, TouchableOpacity, StyleSheet } from 'react-native';
3 |
4 | export default class NavigationItem extends React.Component {
5 | render() {
6 | let icon = this.props.icon &&
7 |
8 |
9 | let title = this.props.title &&
10 | {this.props.title}
11 |
12 | return (
13 |
14 | {icon}
15 | {title}
16 |
17 | )
18 | }
19 | }
20 |
21 | const styles = StyleSheet.create({
22 | container: {
23 | flex: 1,
24 | flexDirection: 'row',
25 | justifyContent: 'center',
26 | alignItems: 'center',
27 | },
28 | icon: {
29 | width: 27,
30 | height: 27,
31 | margin: 8,
32 | },
33 | title: {
34 | fontSize: 15,
35 | color: '#333333',
36 | margin: 8,
37 | }
38 | })
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 |
24 | # Android/IntelliJ
25 | #
26 | build/
27 | .idea
28 | .gradle
29 | local.properties
30 | *.iml
31 | android/captures/*
32 | .project
33 | .classpath
34 | .settings
35 |
36 | # node.js
37 | #
38 | node_modules/
39 | npm-debug.log
40 | yarn-error.log
41 |
42 | # BUCK
43 | buck-out/
44 | \.buckd/
45 | *.keystore
46 | !debug.keystore
47 |
48 | # fastlane
49 | #
50 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
51 | # screenshots whenever they are needed.
52 | # For more information about the recommended setup visit:
53 | # https://docs.fastlane.tools/best-practices/source-control/
54 |
55 | */fastlane/report.xml
56 | */fastlane/Preview.html
57 | */fastlane/screenshots
58 |
59 | # Bundle artifact
60 | *.jsbundle
61 |
62 | # CocoaPods
63 | /ios/Pods/
--------------------------------------------------------------------------------
/src/widgets/text/Text.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { StyleSheet, Text } from 'react-native'
3 |
4 | export function Heading1({ style, ...props }) {
5 | return
6 | }
7 |
8 | export function Heading2({ style, ...props }) {
9 | return
10 | }
11 |
12 | export function Heading3({ style, ...props }) {
13 | return
14 | }
15 |
16 | export function Paragraph({ style, ...props }) {
17 | return
18 | }
19 |
20 | export function Tip({ style, ...props }) {
21 | return
22 | }
23 |
24 | const styles = StyleSheet.create({
25 | h1: {
26 | fontSize: 40,
27 | color: '#333333',
28 | },
29 | h2: {
30 | fontSize: 15,
31 | fontWeight: 'bold',
32 | color: '#222222',
33 | },
34 | h3: {
35 | fontSize: 14,
36 | color: '#222222',
37 | },
38 | p: {
39 | fontSize: 13,
40 | color: '#777777',
41 | },
42 | tip: {
43 | fontSize: 13,
44 | color: '#999999'
45 | }
46 | })
47 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | MaxieeRNLab
2 |
3 |
4 | My React Native learning experiences
5 | Awesome React Native demos.
6 |
7 |
8 | MaxieeRNLab is my learning experiences of React Native. This project includes many aspect of developing a React
9 | Native:
10 |
11 | - A better understand of React Native Framework
12 | - Yoga layout engine
13 | - BatchedBridge message queue
14 | - React Navigation with react-navigation
15 | - stack navigator
16 | - material top tab navigator
17 | - custom bottom navigation with center button
18 | - Redux
19 | - Todo demo
20 | - UI
21 | - usage of react-native-paper
22 | - usage of react-native-elements
23 |
24 | ## Screenshots
25 |
26 | |HomePage|Yoga Layout Engine|Stack Navigator|
27 | |--|--|---|
28 | ||||
29 | |Redux Todo 1|Redux Todo 2|Custom Bottom Navigator|
30 | ||||
31 | |Material Top Tab|Image|Buttons|
32 | ||||
33 | |Chat Demo|Line Chart Demo||
34 | ||||
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext {
5 | buildToolsVersion = "28.0.3"
6 | minSdkVersion = 16
7 | compileSdkVersion = 28
8 | targetSdkVersion = 28
9 | }
10 | repositories {
11 | google()
12 | jcenter()
13 | }
14 | dependencies {
15 | classpath("com.android.tools.build:gradle:3.4.2")
16 |
17 | // NOTE: Do not place your application dependencies here; they belong
18 | // in the individual module build.gradle files
19 | }
20 | }
21 |
22 | allprojects {
23 | repositories {
24 | mavenLocal()
25 | maven {
26 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
27 | url("$rootDir/../node_modules/react-native/android")
28 | }
29 | maven {
30 | // Android JSC is installed from npm
31 | url("$rootDir/../node_modules/jsc-android/dist")
32 | }
33 | google()
34 | jcenter()
35 | maven { url 'https://jitpack.io' }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/pages/demo/DemoHome.js:
--------------------------------------------------------------------------------
1 | import React, {PureComponent} from 'react';
2 | import { ScrollView, View } from 'react-native';
3 | import { Button } from 'react-native-elements';
4 |
5 | export default class DemoHome extends PureComponent {
6 | static navigationOptions = {
7 | title: 'Demos'
8 | }
9 |
10 | render() {
11 | return (
12 |
13 |
14 |
15 |
16 |
17 |
23 | )
24 | }
25 | }
--------------------------------------------------------------------------------
/src/pages/demo/meituan/home/MTHomeMenuItem.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { TouchableOpacity, Image, StyleSheet } from 'react-native';
3 | import screen from '../../../../common/screen';
4 | import { Heading3 } from '../../../../widgets/text/Text';
5 |
6 | const styles = StyleSheet.create({
7 | container: {
8 | justifyContent: 'center',
9 | alignItems: 'center',
10 | width: screen.width / 5,
11 | height: screen.width / 5,
12 | },
13 | icon: {
14 | width: screen.width / 9,
15 | height: screen.width / 9,
16 | margin: 5,
17 | }
18 | });
19 |
20 | export default class MTHomeMenuItem extends Component {
21 | render() {
22 | return (
23 |
25 |
29 |
30 | {this.props.title}
31 |
32 |
33 | )
34 | }
35 | }
--------------------------------------------------------------------------------
/src/demo/NavigationDemo/StackDemo/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createStackNavigator } from '@react-navigation/stack'
3 | import { View, Text, Button } from 'react-native';
4 |
5 | class CompA extends React.Component {
6 | static navigationOptions = { title: "CompA" }
7 |
8 | render() { return CompA }
9 | }
10 |
11 | class CompB extends React.Component {
12 | static navigationOptions = { title: "CompB" }
13 |
14 | render() { return CompB }
15 | }
16 |
17 | let Index = (props) => {
18 | return {
19 | ["CompA", "CompB"].map((v, index) =>
20 | props.navigation.navigate(v)} />)
23 | }
24 | }
25 |
26 | export default () => {
27 | return (
28 |
29 |
32 |
35 |
38 |
39 | )
40 | };
--------------------------------------------------------------------------------
/src/demo/LoginDemo/DemoLogin1.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { View, StyleSheet } from 'react-native';
3 | import Icon from 'react-native-vector-icons/Ionicons';
4 | import { TextInput } from 'react-native-paper';
5 | import GradientButton from '../ReactNativeUIDemo/buttons/GradientButton';
6 |
7 | export default () =>
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | const styles = StyleSheet.create({
19 | container: {
20 | paddingHorizontal: 17,
21 | paddingBottom: 22,
22 | alignItems: 'center',
23 | flexDirection: 'column',
24 | flex: 1
25 | },
26 | buttons: {
27 | flexDirection: 'row',
28 | marginBottom: 24,
29 | marginTop: 200
30 | },
31 | button: {
32 | marginHorizontal: 14,
33 | },
34 | })
35 |
--------------------------------------------------------------------------------
/src/demo/NavigationDemo/Custom/BottomNavigation/HeartBeatBottomNavi/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Text, View } from 'react-native';
3 | import HeartBeatBottomNavigation from "./HeartBeatBottomNavigation";
4 | import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
5 |
6 | let tab1 = () => Tab 1
7 | let tab2 = () => Tab 2
8 | let tab3 = () => Tab 3
9 | let tab4 = () => Tab 4
10 |
11 | const TAB = createBottomTabNavigator();
12 |
13 | export default () => {
14 | return (
15 |
16 |
19 |
22 |
25 |
28 |
29 | )
30 | }
31 | // export default createBottomTabNavigator(
32 | // {
33 | // tab1: tab1,
34 | // tab2: tab2,
35 | // tab3: tab3,
36 | // tab4: tab4
37 | // },
38 | // {
39 | // tabBarComponent: HeartBeatBottomNavigation,
40 | // }
41 | // )
--------------------------------------------------------------------------------
/src/pages/demo/twitter/TwitterPost.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import { ScrollView, RefreshControl, Image } from 'react-native';
3 | import screen from '../../../common/screen';
4 |
5 | export default class TwitterPost extends Component {
6 | constructor(props) {
7 | super(props);
8 |
9 | this.state = {
10 | isRefreshing: false
11 | }
12 | }
13 |
14 | onRefresh() {
15 | this.setState({
16 | isRefreshing: true
17 | });
18 | setTimeout(() => {
19 | this.setState({
20 | isRefreshing: false
21 | })
22 | }, 1000);
23 | }
24 |
25 | render() {
26 | return (
27 | this.onRefresh()}
32 | tintColor="#ddd" />
33 | }>
34 |
40 |
41 | )
42 | }
43 |
44 | }
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
15 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/pages/demo/mylocation/Map.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import MapView from 'react-native-maps';
3 |
4 | export default class Map extends Component {
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | isFirstLoad: true,
10 | mapRegion: undefined,
11 | annotations: []
12 | }
13 | }
14 |
15 | getAnnotations(region) {
16 | return [{
17 | longitude: region.longitude,
18 | latitude: region.latitude,
19 | title: 'You are here!'
20 | }];
21 | }
22 |
23 | onRegionChangeComplete(region) {
24 | if (this.state.isFirstLoad) {
25 | this.setState({
26 | annotations: this.getAnnotations(region),
27 | isFirstLoad: false
28 | })
29 | }
30 | }
31 |
32 | render() {
33 | return (
34 | this.onRegionChangeComplete(region)}
40 | region={this.state.mapRegion}
41 | annotations={this.state.annotations} />
42 | )
43 | }
44 |
45 | }
--------------------------------------------------------------------------------
/src/demo/ChartDemo/DemoLineChart.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { LineChart } from 'react-native-chart-kit'
3 | import { Dimensions } from 'react-native';
4 |
5 |
6 | export default () => {
7 | return (
8 | `rgba(255, 255, 255, ${opacity})`,
30 | style: {
31 | borderRadius: 16
32 | }
33 | }}
34 | bezier
35 | style={{
36 | marginVertical: 8,
37 | borderRadius: 16
38 | }}
39 | />
40 | )
41 | }
--------------------------------------------------------------------------------
/src/pages/demo/meituan/nearby/MTNearbyHeaderView.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { TouchableOpacity, StyleSheet, View } from 'react-native';
3 | import { Paragraph } from '../../../../widgets/text/Text';
4 | import screen from '../../../../common/screen';
5 |
6 | const styles = StyleSheet.create({
7 | container: {
8 | flexDirection: 'row',
9 | flexWrap: 'wrap',
10 | },
11 | item: {
12 | width: screen.width / 4 - 10,
13 | marginLeft: 8,
14 | marginTop: 5,
15 | marginBottom: 5,
16 | height: 30,
17 | justifyContent: 'center',
18 | alignItems: 'center',
19 | borderRadius: 15,
20 | borderWidth: screen.onePixel,
21 | borderColor: '#e0e0e0',
22 | },
23 | })
24 |
25 | export class MTNearbyHeaderView extends Component {
26 | render() {
27 | return (
28 |
29 | {this.props.titles.map((title, i) => (
30 |
33 |
34 | {title}
35 |
36 |
37 | ))}
38 |
39 | )
40 | }
41 | }
--------------------------------------------------------------------------------
/android/app/_BUCK:
--------------------------------------------------------------------------------
1 | # To learn about Buck see [Docs](https://buckbuild.com/).
2 | # To run your application with Buck:
3 | # - install Buck
4 | # - `npm start` - to start the packager
5 | # - `cd android`
6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
8 | # - `buck install -r android/app` - compile, install and run application
9 | #
10 |
11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets")
12 |
13 | lib_deps = []
14 |
15 | create_aar_targets(glob(["libs/*.aar"]))
16 |
17 | create_jar_targets(glob(["libs/*.jar"]))
18 |
19 | android_library(
20 | name = "all-libs",
21 | exported_deps = lib_deps,
22 | )
23 |
24 | android_library(
25 | name = "app-code",
26 | srcs = glob([
27 | "src/main/java/**/*.java",
28 | ]),
29 | deps = [
30 | ":all-libs",
31 | ":build_config",
32 | ":res",
33 | ],
34 | )
35 |
36 | android_build_config(
37 | name = "build_config",
38 | package = "com.maxieernlab",
39 | )
40 |
41 | android_resource(
42 | name = "res",
43 | package = "com.maxieernlab",
44 | res = "src/main/res",
45 | )
46 |
47 | android_binary(
48 | name = "app",
49 | keystore = "//android/keystores:debug",
50 | manifest = "src/main/AndroidManifest.xml",
51 | package_type = "debug",
52 | deps = [
53 | ":app-code",
54 | ],
55 | )
56 |
--------------------------------------------------------------------------------
/ios/MaxieeRNLab/AppDelegate.m:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Facebook, Inc. and its affiliates.
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | */
7 |
8 | #import "AppDelegate.h"
9 |
10 | #import
11 | #import
12 |
13 | @implementation AppDelegate
14 |
15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
16 | {
17 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
18 | RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
19 | moduleName:@"MaxieeRNLab"
20 | initialProperties:nil];
21 |
22 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
23 |
24 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
25 | UIViewController *rootViewController = [UIViewController new];
26 | rootViewController.view = rootView;
27 | self.window.rootViewController = rootViewController;
28 | [self.window makeKeyAndVisible];
29 | return YES;
30 | }
31 |
32 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
33 | {
34 | #if DEBUG
35 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
36 | #else
37 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
38 | #endif
39 | }
40 |
41 | @end
42 |
--------------------------------------------------------------------------------
/ios/MaxieeRNLab-tvOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | NSAppTransportSecurity
26 |
27 | NSExceptionDomains
28 |
29 | localhost
30 |
31 | NSExceptionAllowsInsecureHTTPLoads
32 |
33 |
34 |
35 |
36 | NSLocationWhenInUseUsageDescription
37 |
38 | UILaunchStoryboardName
39 | LaunchScreen
40 | UIRequiredDeviceCapabilities
41 |
42 | armv7
43 |
44 | UISupportedInterfaceOrientations
45 |
46 | UIInterfaceOrientationPortrait
47 | UIInterfaceOrientationLandscapeLeft
48 | UIInterfaceOrientationLandscapeRight
49 |
50 | UIViewControllerBasedStatusBarAppearance
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/src/pages/demo/meituan/widget/GroupPrchaseCell.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { TouchableOpacity, Image, View, StyleSheet } from 'react-native';
3 | import { Heading2, Paragraph } from '../../../../widgets/text/Text';
4 | import screen from '../../../../common/screen';
5 |
6 | const styles = StyleSheet.create({
7 | container: {
8 | flexDirection: 'row',
9 | padding: 10,
10 | borderBottomWidth: screen.onePixel,
11 | borderColor: '#e0e0e0',
12 | backgroundColor: 'white',
13 | },
14 | icon: {
15 | width: 80,
16 | height: 80,
17 | borderRadius: 5,
18 | },
19 | rightContainer: {
20 | flex: 1,
21 | paddingLeft: 20,
22 | paddingRight: 10,
23 | },
24 | price: {
25 | color: "#21C0AE"
26 | }
27 | })
28 |
29 | export class GroupPurchaseCell extends Component {
30 | render() {
31 | let { info } = this.props;
32 | let imageUrl = info.imageUrl.replace('w.h', '160.0');
33 |
34 | return(
35 | this.props.onPress(info)}>
38 |
39 |
40 |
41 | {info.title}
42 | {info.subtitle}
43 |
44 | {info.price}元
45 |
46 |
47 |
48 | )
49 | }
50 | }
--------------------------------------------------------------------------------
/src/widgets/gridview/GridItem.js:
--------------------------------------------------------------------------------
1 | import React, { PureComponent } from 'react'
2 | import { View, StyleSheet, TouchableOpacity, Image, Text } from 'react-native'
3 | import screen from '../../common/screen';
4 | import { Heading2, Heading3 } from '../text/Text';
5 |
6 | export default class GridItem extends PureComponent {
7 | render() {
8 | let info = this.props.info
9 |
10 | let title = info.title
11 | let color = info.color
12 | let subtitle = info.subtitle || info.deputytitle
13 | let imageUrl = info.imageurl
14 |
15 | return (
16 |
19 |
20 | {title}
21 | { subtitle ? {subtitle} : null}
22 |
23 |
24 | { imageUrl ? : null }
25 | { info.icon ? {info.icon} : null}
26 |
27 | )
28 | }
29 | }
30 |
31 | const styles = StyleSheet.create({
32 | container: {
33 | flexDirection: 'row',
34 | justifyContent: 'center',
35 | alignItems: 'center',
36 | width: screen.width / 2 - screen.onePixel,
37 | height: screen.width / 4,
38 | backgroundColor: 'white',
39 | borderBottomWidth: screen.onePixel,
40 | borderRightWidth: screen.onePixel,
41 | borderColor: '#e0e0e0'
42 | },
43 | icon: {
44 | width: screen.width / 9,
45 | height: screen.width / 9,
46 | marginLeft: 10
47 | }
48 | })
--------------------------------------------------------------------------------
/ios/MaxieeRNLab/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | MaxieeRNLab
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | LSRequiresIPhoneOS
26 |
27 | NSAppTransportSecurity
28 |
29 | NSAllowsArbitraryLoads
30 |
31 | NSExceptionDomains
32 |
33 | localhost
34 |
35 | NSExceptionAllowsInsecureHTTPLoads
36 |
37 |
38 |
39 |
40 | NSLocationWhenInUseUsageDescription
41 |
42 | UILaunchStoryboardName
43 | LaunchScreen
44 | UIRequiredDeviceCapabilities
45 |
46 | armv7
47 |
48 | UISupportedInterfaceOrientations
49 |
50 | UIInterfaceOrientationPortrait
51 | UIInterfaceOrientationLandscapeLeft
52 | UIInterfaceOrientationLandscapeRight
53 |
54 | UIViewControllerBasedStatusBarAppearance
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/src/pages/demo/meituan/mine/MTDetailCell.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { Image, View, TouchableOpacity, StyleSheet } from 'react-native';
3 | import { Heading3, Paragraph } from '../../../../widgets/text/Text';
4 | import screen from '../../../../common/screen';
5 |
6 | const styles = StyleSheet.create({
7 | container: {
8 | backgroundColor: 'white',
9 | },
10 | content: {
11 | height: 44,
12 | flexDirection: 'row',
13 | alignItems: 'center',
14 | paddingLeft: 15,
15 | paddingRight: 10,
16 | },
17 | icon: {
18 | width: 25,
19 | height: 25,
20 | marginRight: 10,
21 | },
22 | subtitleContainer: {
23 | flexDirection: 'row',
24 | justifyContent: 'flex-end',
25 | alignItems: 'center',
26 | },
27 | arrow: {
28 | width: 14,
29 | height: 14,
30 | marginLeft: 5,
31 | }
32 | })
33 |
34 | export default class DetailCell extends Component {
35 | render() {
36 | let icon = this.props.image &&
37 |
38 | return (
39 |
40 |
41 |
42 | {icon}
43 | {this.props.title}
44 |
45 | {this.props.subtitle}
46 |
47 |
48 |
49 |
54 |
55 |
56 |
57 | )
58 | }
59 | }
--------------------------------------------------------------------------------
/src/pages/demo/mylocation/MyLocationHome.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import MapView from 'react-native-maps';
3 | import Map from './Map';
4 | import screen from '../../../common/screen';
5 | import { TouchableHighlight, Text, View } from 'react-native';
6 |
7 | export default class MyLocationHome extends Component {
8 | constructor(props) {
9 | super(props);
10 | this.state = {
11 | showGeo: false
12 | }
13 | }
14 |
15 | getLocation() {
16 | this.setState({
17 | showGeo: true
18 | })
19 | }
20 |
21 | render() {
22 | return (
23 |
27 |
35 | this.getLocation()} >
48 | Find my location
53 |
54 |
55 | )
56 | }
57 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "MaxieeRNLab",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "android": "react-native run-android",
7 | "ios": "react-native run-ios",
8 | "start": "react-native start",
9 | "test": "jest",
10 | "lint": "eslint ."
11 | },
12 | "dependencies": {
13 | "@react-native-community/masked-view": "^0.1.7",
14 | "@react-navigation/bottom-tabs": "^5.2.4",
15 | "@react-navigation/material-top-tabs": "^5.1.7",
16 | "@react-navigation/native": "^5.1.3",
17 | "@react-navigation/stack": "^5.2.8",
18 | "react": "^16.9.0",
19 | "react-native": "^0.61.5",
20 | "react-native-chart-kit": "^5.2.0",
21 | "react-native-elements": "^1.2.7",
22 | "react-native-gesture-handler": "^1.6.1",
23 | "react-native-gifted-chat": "^0.13.0",
24 | "react-native-intent-launcher": "^0.2.0",
25 | "react-native-linear-gradient": "^2.5.4",
26 | "react-native-maps": "^0.27.1",
27 | "react-native-markdown-renderer": "^3.2.8",
28 | "react-native-page-control": "^1.1.1",
29 | "react-native-paper": "^3.6.0",
30 | "react-native-reanimated": "^1.7.1",
31 | "react-native-safe-area-context": "^0.7.3",
32 | "react-native-screens": "^2.4.0",
33 | "react-native-scrollable-tab-view": "^1.0.0",
34 | "react-native-svg": "^9.3.7",
35 | "react-native-swiper": "^1.6.0-rc.3",
36 | "react-native-tab-view": "^2.13.0",
37 | "react-native-ui-kitten": "^3.1.2",
38 | "react-native-vector-icons": "^6.3.0",
39 | "react-native-viewpager": "^0.2.13",
40 | "react-navigation-stack": "^2.3.6",
41 | "react-redux": "^6.0.1",
42 | "redux": "^4.0.1",
43 | "redux-thunk": "^2.3.0"
44 | },
45 | "devDependencies": {
46 | "@babel/core": "^7.6.2",
47 | "@babel/runtime": "^7.6.2",
48 | "@react-native-community/eslint-config": "0.0.5",
49 | "babel-jest": "^24.9.0",
50 | "jest": "^24.9.0",
51 | "metro-react-native-babel-preset": "^0.56.0",
52 | "react-test-renderer": "^16.9.0"
53 | },
54 | "jest": {
55 | "preset": "react-native"
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/ios/MaxieeRNLabTests/MaxieeRNLabTests.m:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Facebook, Inc. and its affiliates.
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | */
7 |
8 | #import
9 | #import
10 |
11 | #import
12 | #import
13 |
14 | #define TIMEOUT_SECONDS 600
15 | #define TEXT_TO_LOOK_FOR @"Welcome to React Native!"
16 |
17 | @interface MaxieeRNLabTests : XCTestCase
18 |
19 | @end
20 |
21 | @implementation MaxieeRNLabTests
22 |
23 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test
24 | {
25 | if (test(view)) {
26 | return YES;
27 | }
28 | for (UIView *subview in [view subviews]) {
29 | if ([self findSubviewInView:subview matching:test]) {
30 | return YES;
31 | }
32 | }
33 | return NO;
34 | }
35 |
36 | - (void)testRendersWelcomeScreen
37 | {
38 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
39 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
40 | BOOL foundElement = NO;
41 |
42 | __block NSString *redboxError = nil;
43 | #ifdef DEBUG
44 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
45 | if (level >= RCTLogLevelError) {
46 | redboxError = message;
47 | }
48 | });
49 | #endif
50 |
51 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
52 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
53 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
54 |
55 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) {
56 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
57 | return YES;
58 | }
59 | return NO;
60 | }];
61 | }
62 |
63 | #ifdef DEBUG
64 | RCTSetLogFunction(RCTDefaultLogFunction);
65 | #endif
66 |
67 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
68 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
69 | }
70 |
71 |
72 | @end
73 |
--------------------------------------------------------------------------------
/.flowconfig:
--------------------------------------------------------------------------------
1 | [ignore]
2 | ; We fork some components by platform
3 | .*/*[.]android.js
4 |
5 | ; Ignore "BUCK" generated dirs
6 | /\.buckd/
7 |
8 | ; Ignore polyfills
9 | node_modules/react-native/Libraries/polyfills/.*
10 |
11 | ; These should not be required directly
12 | ; require from fbjs/lib instead: require('fbjs/lib/warning')
13 | node_modules/warning/.*
14 |
15 | ; Flow doesn't support platforms
16 | .*/Libraries/Utilities/LoadingView.js
17 |
18 | [untyped]
19 | .*/node_modules/@react-native-community/cli/.*/.*
20 |
21 | [include]
22 |
23 | [libs]
24 | node_modules/react-native/Libraries/react-native/react-native-interface.js
25 | node_modules/react-native/flow/
26 |
27 | [options]
28 | emoji=true
29 |
30 | esproposal.optional_chaining=enable
31 | esproposal.nullish_coalescing=enable
32 |
33 | module.file_ext=.js
34 | module.file_ext=.json
35 | module.file_ext=.ios.js
36 |
37 | munge_underscores=true
38 |
39 | module.name_mapper='^react-native$' -> '/node_modules/react-native/Libraries/react-native/react-native-implementation'
40 | module.name_mapper='^react-native/\(.*\)$' -> '/node_modules/react-native/\1'
41 | module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '/node_modules/react-native/Libraries/Image/RelativeImageStub'
42 |
43 | suppress_type=$FlowIssue
44 | suppress_type=$FlowFixMe
45 | suppress_type=$FlowFixMeProps
46 | suppress_type=$FlowFixMeState
47 |
48 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)
49 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+
50 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
51 |
52 | [lints]
53 | sketchy-null-number=warn
54 | sketchy-null-mixed=warn
55 | sketchy-number=warn
56 | untyped-type-import=warn
57 | nonstrict-import=warn
58 | deprecated-type=warn
59 | unsafe-getters-setters=warn
60 | inexact-spread=warn
61 | unnecessary-invariant=warn
62 | signature-verification-failure=warn
63 | deprecated-utility=error
64 |
65 | [strict]
66 | deprecated-type
67 | nonstrict-import
68 | sketchy-null
69 | unclear-type
70 | unsafe-getters-setters
71 | untyped-import
72 | untyped-type-import
73 |
74 | [version]
75 | ^0.105.0
--------------------------------------------------------------------------------
/src/demo/ReactNativeUIDemo/DemoButton.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import { View, TouchableOpacity, StyleSheet } from 'react-native';
3 | import { Text } from 'react-native-elements';
4 | import { RkButton, RkText } from 'react-native-ui-kitten';
5 | import LinearGradient from 'react-native-linear-gradient';
6 | import { Button as ButtonPaper } from 'react-native-paper'
7 | import GradientButton from './buttons/GradientButton';
8 |
9 | export default () => {
10 | let createDemo = (title, Comp) =>
11 | {title}
12 | {Comp}
13 |
14 |
15 | let createTitle = (title) => {title}
16 | return (
17 |
18 | {createTitle("Normal Button")}
19 | {createDemo(
20 | "UI Kitten",
21 | Button)}
22 | {createTitle("Gradient Button")}
23 | {createDemo(
24 | "RN TouchableOpacity",
25 |
26 | )}
27 | {createDemo(
28 | "RN TouchableOpacity Border",
29 |
34 |
35 |
36 | Button
37 |
38 |
39 |
40 | )}
41 |
42 | )
43 | }
44 |
45 | const styles = StyleSheet.create({
46 | buttonContainer: {
47 | width: 200,
48 | alignItems: 'center',
49 | },
50 | buttonTextBorder: {
51 | textAlign: 'center',
52 | color: '#4C64FF',
53 | padding: 15,
54 | marginLeft: 1,
55 | marginRight: 1,
56 | width: 198,
57 | height: 46,
58 | marginTop: 1,
59 | marginBottom: 1,
60 | backgroundColor: 'white'
61 | },
62 | demoText: {
63 | marginTop: 20,
64 | marginBottom: 12
65 | },
66 | header: {
67 | marginTop: 20
68 | }
69 | });
--------------------------------------------------------------------------------
/android/app/src/main/java/com/maxieernlab/MainApplication.java:
--------------------------------------------------------------------------------
1 | package com.maxieernlab;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 |
6 | import com.facebook.react.PackageList;
7 | import com.facebook.react.ReactApplication;
8 | import com.facebook.react.ReactNativeHost;
9 | import com.facebook.react.ReactPackage;
10 | import com.facebook.soloader.SoLoader;
11 |
12 | import java.lang.reflect.InvocationTargetException;
13 | import java.util.List;
14 |
15 | public class MainApplication extends Application implements ReactApplication {
16 |
17 | private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
18 | @Override
19 | public boolean getUseDeveloperSupport() {
20 | return BuildConfig.DEBUG;
21 | }
22 |
23 | @Override
24 | protected List getPackages() {
25 | List packages = new PackageList(this).getPackages();
26 | return packages;
27 | }
28 |
29 | @Override
30 | protected String getJSMainModuleName() {
31 | return "index";
32 | }
33 | };
34 |
35 | @Override
36 | public ReactNativeHost getReactNativeHost() {
37 | return mReactNativeHost;
38 | }
39 |
40 | @Override
41 | public void onCreate() {
42 | super.onCreate();
43 | SoLoader.init(this, /* native exopackage */ false);
44 | initializeFlipper(this); // Remove this line if you don't want Flipper enabled
45 | }
46 |
47 | /**
48 | * Loads Flipper in React Native templates.
49 | *
50 | * @param context
51 | */
52 | private static void initializeFlipper(Context context) {
53 | if (BuildConfig.DEBUG) {
54 | try {
55 | /*
56 | We use reflection here to pick up the class that initializes Flipper,
57 | since Flipper library is not available in release mode
58 | */
59 | Class> aClass = Class.forName("com.facebook.flipper.ReactNativeFlipper");
60 | aClass.getMethod("initializeFlipper", Context.class).invoke(null, context);
61 | } catch (ClassNotFoundException e) {
62 | e.printStackTrace();
63 | } catch (NoSuchMethodException e) {
64 | e.printStackTrace();
65 | } catch (IllegalAccessException e) {
66 | e.printStackTrace();
67 | } catch (InvocationTargetException e) {
68 | e.printStackTrace();
69 | }
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/pages/demo/twitter/TwitterTab.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import { StyleSheet, View, Text, TouchableOpacity } from 'react-native';
3 | import Icon from 'react-native-vector-icons/Ionicons';
4 |
5 | const styles = StyleSheet.create({
6 | title:{
7 | color:"#fff",
8 | fontSize:20,
9 | paddingLeft: 10
10 | },
11 | tabs: {
12 | height: 45,
13 | flexDirection: 'row',
14 | paddingTop: 5,
15 | borderWidth: 1,
16 | borderTopWidth: 0,
17 | borderLeftWidth: 0,
18 | borderRightWidth: 0,
19 | borderBottomColor: 'rgba(0,0,0,0.05)',
20 | backgroundColor:"#111"
21 | },
22 | tab: {
23 | flex: 1,
24 | alignItems: 'center',
25 | justifyContent: 'center',
26 | paddingBottom: 10,
27 | },
28 | })
29 |
30 | export class FacebookTabBar extends Component {
31 | constructor(props) {
32 | super(props);
33 | this.tabIcons = [];
34 | this.setAnimationValue = this.setAnimationValue.bind(this);
35 | }
36 |
37 | componentDidMount() {
38 | setTimeout(() => this.props.gotoPage(0), 0);
39 | this.listener = this.props.scrollValue.addListener(this.setAnimationValue);
40 | }
41 |
42 | setAnimationValue({value}) {
43 | this.tabIcons.forEach((icon, i) => {
44 | const progress = (value - i >= 0 && value - i <= 1) ? value - i : 1;
45 | icon.setNativeProps({
46 | style: {
47 | color: this.iconColor(progress),
48 | },
49 | });
50 | });
51 | }
52 |
53 | iconColor(progress) {
54 | const red = 49 + (159 - 49) * progress;
55 | const green = 149 + (159 - 149) * progress;
56 | const blue = 215 + (159 - 215) * progress;
57 | return `rgb(${red}, ${green}, ${blue})`;
58 | }
59 |
60 | render() {
61 | return
62 | {this.props.tabs.map((tab, i) => {
63 | return setTimeout(() => this.props.gotoPage(i), 0)}
66 | style={styles.tab}>
67 | { this.tabIcons[i] = icon; }} />
72 |
73 | })}
74 |
75 | }
76 | }
77 |
78 |
--------------------------------------------------------------------------------
/src/pages/basic/RNBasicScrollView.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { View, Text, ScrollView, StyleSheet } from 'react-native';
3 | import { Heading2 } from '../../widgets/text/Text';
4 | import PageControl from 'react-native-page-control';
5 | import screen from '../../common/screen';
6 |
7 | const styles = StyleSheet.create({
8 | scrollView: {
9 | height: 100,
10 | borderWidth: 1,
11 | borderColor: 'red'
12 | },
13 | heading: {
14 | margin: 10
15 | }
16 | });
17 |
18 | export default class RNBasicScrollView extends React.Component {
19 | constructor(props) {
20 | super(props);
21 |
22 | this.state = {
23 | currentPage: 0
24 | }
25 | }
26 |
27 | onScroll(e) {
28 | let x = e.nativeEvent.contentOffset.x;
29 | let currentPage = Math.round(x / screen.width);
30 |
31 | if (this.state.currentPage != currentPage) {
32 | this.setState({
33 | currentPage: currentPage
34 | })
35 | }
36 | }
37 |
38 | render() {
39 | let items = []
40 |
41 | for (let i = 0; i < 10; i++) {
42 | items.push({i})
50 | }
51 |
52 | return (
53 |
54 | Basic ScrollView
55 |
56 | {items}
57 |
58 | Horizontal ScrollView
59 |
60 | {items}
61 |
62 | PagingEnabled ScrollView
63 | this.onScroll(e)}>
65 | {items}
66 | {items}
67 |
68 |
75 |
76 | )
77 | }
78 | }
--------------------------------------------------------------------------------
/ios/Podfile:
--------------------------------------------------------------------------------
1 | platform :ios, '9.0'
2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
3 |
4 | target 'MaxieeRNLab' do
5 | # Pods for RnDiffApp
6 | pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
7 | pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
8 | pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
9 | pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
10 | pod 'React', :path => '../node_modules/react-native/'
11 | pod 'React-Core', :path => '../node_modules/react-native/'
12 | pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
13 | pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
14 | pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
15 | pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
16 | pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
17 | pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
18 | pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
19 | pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
20 | pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
21 | pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
22 | pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
23 | pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/'
24 | pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
25 | pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
26 | pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
27 | pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
28 | pod 'ReactCommon/jscallinvoker', :path => "../node_modules/react-native/ReactCommon"
29 | pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
30 | pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
31 | pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
32 | pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
33 | pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
34 |
35 | target 'RnDiffAppTests' do
36 | inherit! :search_paths
37 | # Pods for testing
38 | end
39 | use_native_modules!
40 | end
41 |
42 | target 'RnDiffApp-tvOS' do
43 | # Pods for RnDiffApp-tvOS
44 | target 'RnDiffApp-tvOSTests' do
45 | inherit! :search_paths
46 | # Pods for testing
47 | end
48 |
49 | end
--------------------------------------------------------------------------------
/src/pages/demo/meituan/home/MTHomeMenuView.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import MTHomeMenuItem from './MTHomeMenuItem';
3 | import { StyleSheet, View, ScrollView } from 'react-native';
4 | import screen from '../../../../common/screen';
5 | import PageControl from 'react-native-page-control'
6 |
7 | const styles = StyleSheet.create({
8 | container: {
9 | backgroundColor: 'white',
10 | },
11 | menuContainer: {
12 | flexDirection: 'row',
13 | },
14 | itemsView: {
15 | flexDirection: 'row',
16 | flexWrap: 'wrap',
17 | width: screen.width,
18 | },
19 | pageControl: {
20 | margin: 10,
21 | }
22 | })
23 |
24 | export default class MTHomeMenuView extends Component {
25 | constructor(props) {
26 | super(props);
27 |
28 | this.state = {
29 | currentPage: 0
30 | }
31 | }
32 |
33 | onScroll(e) {
34 | let x = e.nativeEvent.contentOffset.x;
35 | let currentPage = Math.round(x / screen.width)
36 |
37 | if (this.state.currentPage != currentPage) {
38 | this.setState({
39 | currentPage: currentPage
40 | })
41 | }
42 | }
43 |
44 | render() {
45 | let { menuInfos, onMenuSelected } = this.props;
46 |
47 | let menuItems = menuInfos.map((info, i) => (
48 | {
53 | onMenuSelected && onMenuSelected(i)
54 | }} />
55 | ))
56 |
57 | let menuViews = []
58 | let pageCount = Math.ceil(menuInfos.length / 10)
59 |
60 | for (let i = 0; i < pageCount; i++) {
61 | let items = menuItems.slice(i * 10, i * 10 + 10)
62 |
63 | let menuView = (
64 |
65 | {items}
66 |
67 | )
68 | menuViews.push(menuView);
69 | }
70 |
71 | return (
72 |
73 | this.onScroll(e)}>
78 |
79 | {menuViews}
80 |
81 |
82 |
90 |
91 |
92 | )
93 | }
94 |
95 | }
--------------------------------------------------------------------------------
/android/app/src/main/java/com/maxieernlab/yoga/YogaActivity2.java:
--------------------------------------------------------------------------------
1 | package com.maxieernlab.yoga;
2 |
3 | import android.graphics.Color;
4 | import android.os.Bundle;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.FrameLayout;
8 |
9 | import androidx.appcompat.app.AppCompatActivity;
10 |
11 | import com.facebook.yoga.YogaEdge;
12 | import com.facebook.yoga.YogaFlexDirection;
13 | import com.facebook.yoga.YogaNode;
14 | import com.facebook.yoga.YogaNodeJNIFinalizer;
15 |
16 | import javax.annotation.Nullable;
17 |
18 | public class YogaActivity2 extends AppCompatActivity {
19 | private static final int VIEW_WIDTH = 200;
20 |
21 | @Override
22 | protected void onCreate(@Nullable Bundle savedInstanceState) {
23 | super.onCreate(savedInstanceState);
24 |
25 | FrameLayout container = new FrameLayout(this);
26 |
27 | /**
28 | * 纯布局数值计算
29 | */
30 |
31 | float screenWidth = getWindowManager().getDefaultDisplay().getWidth();
32 | float screenHeight = getWindowManager().getDefaultDisplay().getHeight();
33 |
34 | YogaNode root = new YogaNodeJNIFinalizer();
35 | root.setWidth(screenWidth);
36 | root.setHeight(screenHeight);
37 | root.setFlexDirection(YogaFlexDirection.ROW);
38 |
39 | YogaNode rect1 = new YogaNodeJNIFinalizer();
40 | rect1.setHeight(VIEW_WIDTH);
41 | rect1.setWidth(VIEW_WIDTH);
42 | rect1.setMargin(YogaEdge.ALL, 20);
43 |
44 | YogaNode rect2 = new YogaNodeJNIFinalizer();
45 | rect2.setHeight(VIEW_WIDTH);
46 | rect2.setWidth(VIEW_WIDTH);
47 | rect2.setMargin(YogaEdge.ALL, 20);
48 |
49 | YogaNode rect3 = new YogaNodeJNIFinalizer();
50 | rect3.setHeight(VIEW_WIDTH);
51 | rect3.setWidth(VIEW_WIDTH);
52 | rect3.setMargin(YogaEdge.ALL, 20);
53 |
54 | root.addChildAt(rect1, 0);
55 | root.addChildAt(rect2, 1);
56 | root.addChildAt(rect3, 2);
57 |
58 | // 给定屏幕长宽,求解屏幕元素位置
59 | root.calculateLayout(screenWidth, screenHeight);
60 |
61 | /**
62 | * Android 视图创建于定位
63 | */
64 | ViewGroup.LayoutParams lp = new FrameLayout.LayoutParams(VIEW_WIDTH, VIEW_WIDTH);
65 |
66 | View v1 = new View(this);
67 | v1.setLayoutParams(lp);
68 | v1.setBackgroundColor(Color.parseColor("#d50000"));
69 |
70 | View v2 = new View(this);
71 | v2.setLayoutParams(lp);
72 | v2.setBackgroundColor(Color.parseColor("#ff1744"));
73 |
74 | View v3 = new View(this);
75 | v3.setLayoutParams(lp);
76 | v3.setBackgroundColor(Color.parseColor("#ff5252"));
77 |
78 | container.addView(v1);
79 | container.addView(v2);
80 | container.addView(v3);
81 |
82 | v1.setX(rect1.getLayoutX());
83 | v1.setY(rect1.getLayoutY());
84 | v2.setX(rect2.getLayoutX());
85 | v2.setY(rect2.getLayoutY());
86 | v3.setX(rect3.getLayoutX());
87 | v3.setY(rect3.getLayoutY());
88 |
89 | setContentView(container);
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem http://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
34 |
35 | @rem Find java.exe
36 | if defined JAVA_HOME goto findJavaFromJavaHome
37 |
38 | set JAVA_EXE=java.exe
39 | %JAVA_EXE% -version >NUL 2>&1
40 | if "%ERRORLEVEL%" == "0" goto init
41 |
42 | echo.
43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
44 | echo.
45 | echo Please set the JAVA_HOME variable in your environment to match the
46 | echo location of your Java installation.
47 |
48 | goto fail
49 |
50 | :findJavaFromJavaHome
51 | set JAVA_HOME=%JAVA_HOME:"=%
52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
53 |
54 | if exist "%JAVA_EXE%" goto init
55 |
56 | echo.
57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
58 | echo.
59 | echo Please set the JAVA_HOME variable in your environment to match the
60 | echo location of your Java installation.
61 |
62 | goto fail
63 |
64 | :init
65 | @rem Get command-line arguments, handling Windows variants
66 |
67 | if not "%OS%" == "Windows_NT" goto win9xME_args
68 |
69 | :win9xME_args
70 | @rem Slurp the command line arguments.
71 | set CMD_LINE_ARGS=
72 | set _SKIP=2
73 |
74 | :win9xME_args_slurp
75 | if "x%~1" == "x" goto execute
76 |
77 | set CMD_LINE_ARGS=%*
78 |
79 | :execute
80 | @rem Setup the command line
81 |
82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
83 |
84 | @rem Execute Gradle
85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
86 |
87 | :end
88 | @rem End local scope for the variables with windows NT shell
89 | if "%ERRORLEVEL%"=="0" goto mainEnd
90 |
91 | :fail
92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
93 | rem the _cmd.exe /c_ return code!
94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
95 | exit /b 1
96 |
97 | :mainEnd
98 | if "%OS%"=="Windows_NT" endlocal
99 |
100 | :omega
101 |
--------------------------------------------------------------------------------
/src/pages/demo/meituan/nearby/MTNearbyScene.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { TouchableOpacity, StyleSheet, Image, View, Text } from 'react-native';
3 | import screen from '../../../../common/screen';
4 | import { Paragraph } from '../../../../widgets/text/Text';
5 | import ScrollableTabView from 'react-native-scrollable-tab-view'
6 | import { MTNearbyHeaderView } from './MTNearbyHeaderView';
7 |
8 | const styles = StyleSheet.create({
9 | container: {
10 | flex: 1,
11 | backgroundColor: '#f3f3f3'
12 | },
13 | searchBar: {
14 | width: screen.width * 0.65,
15 | height: 30,
16 | borderRadius: 19,
17 | flexDirection: 'row',
18 | justifyContent: 'center',
19 | alignItems: 'center',
20 | backgroundColor: '#eeeeee',
21 | alignSelf: 'center',
22 | marginRight: 20,
23 | },
24 | searchIcon: {
25 | width: 20,
26 | height: 20,
27 | margin: 5,
28 | },
29 | tabBarText: {
30 | fontSize: 14,
31 | marginTop: 13,
32 | },
33 | tabBarUnderline: {
34 | backgroundColor: '#FE566D'
35 | },
36 | })
37 |
38 | export default class MTNearbyScene extends Component {
39 | static navigationOptions = {
40 | headerRight: (
41 |
42 |
45 | 找附近的吃喝玩乐
46 |
47 | ),
48 | headerLeft: (
49 |
55 |
57 | 福州 鼓楼
58 |
59 | ),
60 | headerStyle: { backgroundColor: 'white' },
61 | }
62 |
63 | render() {
64 | let titles = ['享美食', '住酒店', '爱玩乐', '全部']
65 | let types = [
66 | ['热门', '面包甜点', '小吃快餐', '川菜', '日本料理', '韩国料理', '台湾菜', '东北菜'],
67 | ['热门', '商务出行', '公寓民宿', '情侣专享', '高星特惠'],
68 | ['热门', 'KTV', '足疗按摩', '洗浴汗蒸', '电影院', '美发', '美甲'],
69 | []
70 | ]
71 | return (
72 |
78 | {titles.map((title, i) => (
79 |
85 |
88 |
89 | ))}
90 |
91 | )
92 | }
93 | }
--------------------------------------------------------------------------------
/src/demo/ChatDemo/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {GiftedChat, Actions, Bubble, SystemMessage} from 'react-native-gifted-chat';
3 | import { View, Text, Button } from 'react-native';
4 | import GradientButton from '../ReactNativeUIDemo/buttons/GradientButton'
5 |
6 | let messages = [
7 | {
8 | _id: 2,
9 | text: "World!",
10 | createdAt: new Date(Date.UTC(2019, 3, 1, 1, 0, 0)),
11 | user: {
12 | _id: 2,
13 | name: "Judy"
14 | },
15 | sent: true,
16 | received: true
17 | },
18 | {
19 | _id: 1,
20 | text: "hello",
21 | createdAt: new Date(Date.UTC(2019, 3, 1, 2, 0, 0)),
22 | user: {
23 | _id: 1,
24 | name: "MaxieeBot"
25 | },
26 | sent: true,
27 | received: true
28 | }, {
29 | _id: 3,
30 | text: 'I am system message',
31 | createdAt: new Date(Date.UTC(2019,32, 1, 3, 0, 0)),
32 | system: true,
33 | }
34 | ]
35 |
36 | export default class ChatDemo extends React.Component {
37 |
38 | state = {
39 | messages: messages,
40 | }
41 |
42 | constructor(props) {
43 | super(props)
44 |
45 | this.onSend = this.onSend.bind(this)
46 | this.renderCustomActions = this.renderCustomActions.bind(this)
47 | this.renderBubble = this.renderBubble.bind(this)
48 | this.renderCustomView = this.renderCustomView.bind(this)
49 | }
50 |
51 | onSend(messages = []) {
52 | this.setState((previousState) => {
53 | return {
54 | messages: GiftedChat.append(previousState.messages, messages)
55 | }
56 | })
57 | }
58 |
59 | renderCustomActions(props) {
60 | const options = {
61 | 'Action 1': (props) => {
62 | props.onSend({
63 | comp:
64 | })
65 | },
66 | 'Action 2': (props) => {
67 | props.onSend({
68 | buttonText: "OMG!"
69 | })
70 | },
71 | 'Cancel': () => {},
72 | };
73 | return (
74 |
78 | )
79 | }
80 |
81 | renderBubble(props) {
82 | return (
83 |
90 | )
91 | }
92 |
93 | renderCustomView(props) {
94 | if (props.currentMessage.buttonText) {
95 | return alert("aHa!")}
97 | text={props.currentMessage.buttonText} />
98 | } else if (props.currentMessage.comp) {
99 | return props.currentMessage.comp
100 | }
101 | return null
102 | }
103 |
104 | render() {
105 | return (
106 |
113 | )
114 | }
115 | }
--------------------------------------------------------------------------------
/src/pages/demo/meituan/MeituanHome.js:
--------------------------------------------------------------------------------
1 | import React, {PureComponent} from 'react';
2 | import { createStackNavigator } from '@react-navigation/stack';
3 | import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
4 | import MTHomeScene from './home/MTHomeScene';
5 | import TabBarItem from '../../../widgets/tab/bottom/TabBarItem';
6 | import { MTMineScene } from './mine/MTMineScene';
7 | import MTNearbyScene from './nearby/MTNearbyScene';
8 |
9 | const Tab = createBottomTabNavigator();
10 | const Stack = createStackNavigator();
11 |
12 | export default () => {
13 | return (
14 |
15 |
19 |
22 |
23 | } />
24 |
28 |
31 |
32 | } />
33 |
37 |
40 |
41 | } />
42 |
43 | )
44 |
45 | }
46 |
47 | // const Tab = createBottomTabNavigator({
48 | // Home: {
49 | // screen: createStackNavigator({Home: MTHomeScene}),
50 | // navigationOptions: {
51 | // tabBarLabel: '团购',
52 | // tabBarIcon: ({focused, tintColor}) => (
53 | //
59 | // )
60 | // }
61 | // },
62 | // Nearby: {
63 | // screen: createStackNavigator({Nearby: MTNearbyScene}),
64 | // navigationOptions: {
65 | // tabBarLabel: '附近',
66 | // tabBarIcon: ({focused, tintColor}) => (
67 | //
73 | // )
74 | // }
75 | // },
76 | // Mine: {
77 | // screen: createStackNavigator({Mine: MTMineScene}),
78 | // navigationOptions: {
79 | // tabBarLabel: '我的',
80 | // tabBarIcon: ({ focused, tintColor }) => (
81 | //
86 | // )
87 | // }
88 | // }
89 | // }, {
90 | // lazy: true,
91 | // animationEnabled: false,
92 | // swipeEnabled: false
93 | // })
94 |
95 | // Tab.navigationOptions = {
96 | // header: null
97 | // }
98 |
99 | // export default Tab;
--------------------------------------------------------------------------------
/ios/MaxieeRNLab/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
24 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/src/demo/ReduxDemo/demos/ReduxTodo.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { View, Text } from 'react-native';
3 | import todoAdd from '../../../reducers/todo/actions/todo-add'
4 | import todoFinish from '../../../reducers/todo/actions/todo-finish'
5 | import todoUnfinish from '../../../reducers/todo/actions/todo-unfinish'
6 | import { connect } from 'react-redux'
7 | import { Button, List, Dialog, Portal, TextInput } from 'react-native-paper';
8 |
9 | class Component extends React.Component {
10 | state = {
11 | dialogVisible: false,
12 | dialogInputTodoName: "",
13 | }
14 |
15 | _showDialog = () => this.setState({ dialogVisible: true })
16 |
17 | _hideDialog = () => this.setState({ dialogVisible: false })
18 |
19 | render() {
20 | const {todo, todoAdd, todoFinish, todoUnfinish} = this.props;
21 |
22 | console.log(todo)
23 | return
24 |
25 | this._showDialog()}>add
29 |
30 |
63 |
64 | {
65 | todo.todos.map((v,index) => (
66 | {
71 | v.finished ? "DONE" : "TODO"
72 | }}
73 | right={props => {
75 | v.finished ? todoUnfinish(v.id) : todoFinish(v.id)
76 | }}>{
77 | v.finished ? "❎" : "✅"
78 | }} />
79 | ))
80 | }
81 |
82 |
83 | }
84 | }
85 |
86 | const mapStateToProps = ({todo}) => ({todo})
87 | const actions = {todoAdd, todoFinish, todoUnfinish}
88 |
89 | export default connect(mapStateToProps, actions)(Component)
--------------------------------------------------------------------------------
/src/demo/NavigationDemo/Custom/BottomNavigation/HeartBeatBottomNavi/HeartBeatBottomNavigation.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { View, TouchableWithoutFeedback, StyleSheet } from 'react-native';
3 | import Icon from 'react-native-vector-icons/Ionicons'
4 |
5 | const HEIGHT_TABBAR = 48
6 | const HEIGHT_CIRCLE = 56
7 |
8 | /**
9 | * references:
10 | * 1. https://medium.com/@sxia/how-to-customize-tab-bar-in-react-navigation-a0dc6d4d7e61
11 | * 2. https://maxiee.github.io/post/ReactNavigationCustomTabBar.md/
12 | */
13 | export default class HeartBeatBottomNavigation extends React.Component {
14 | constructor(props) {
15 | super(props)
16 | }
17 |
18 | renderIcon() {
19 | return
20 | }
21 |
22 | renderTabButton(route, index) {
23 | const {
24 | activeTintColor,
25 | inactiveTintColor,
26 | navigation,
27 | getLabelText,
28 | renderIcon
29 | } = this.props
30 |
31 | const currentIndex = navigation.state.index;
32 | const label = getLabelText({ route, focused: currentIndex === index, index: index });
33 |
34 | return (
35 |
37 | {
39 | navigation.navigate(route.routeName)
40 | }}>
41 |
42 | {this.renderIcon()}
43 | {/* {label} */}
46 |
47 |
48 |
49 | )
50 | }
51 |
52 | render() {
53 | const { navigation, style } = this.props;
54 | let tabBarButtons = navigation.state.routes.map(this.renderTabButton.bind(this));
55 |
56 | tabBarButtons.splice(2, 0,
57 | )
61 |
62 | return (
63 |
64 |
65 | {tabBarButtons}
66 |
67 |
68 |
72 |
73 |
74 | );
75 | }
76 | }
77 |
78 | const styles = StyleSheet.create({
79 | container: {
80 | flex: 1,
81 | justifyContent: 'center',
82 | alignItems: 'center',
83 | height: HEIGHT_CIRCLE
84 | },
85 | tabbarContainer: {
86 | position: 'absolute',
87 | bottom: 0,
88 | left: 0,
89 | right: 0,
90 | borderTopWidth: 0.5,
91 | height: HEIGHT_TABBAR,
92 | flex: 1,
93 | justifyContent: 'space-evenly',
94 | flexDirection: 'row',
95 | borderTopColor: "#CCCCCC",
96 | },
97 | circleButton: {
98 | width: HEIGHT_CIRCLE,
99 | height: HEIGHT_CIRCLE,
100 | position: 'absolute',
101 | bottom: 4,
102 | borderRadius: HEIGHT_CIRCLE/2,
103 | backgroundColor: 'pink',
104 | borderWidth: 0.5,
105 | borderColor: 'white',
106 | flex: 1,
107 | justifyContent: 'center',
108 | alignItems: 'center',
109 | },
110 | tabButtonSizer: {
111 | height: HEIGHT_TABBAR,
112 | width: HEIGHT_TABBAR,
113 | },
114 | tabButtonContainer: {
115 | flex: 1,
116 | flexDirection: 'column',
117 | justifyContent: 'center',
118 | alignItems: 'center',
119 | }
120 | })
--------------------------------------------------------------------------------
/android/app/src/main/java/com/maxieernlab/yoga/YogaActivity1.java:
--------------------------------------------------------------------------------
1 | package com.maxieernlab.yoga;
2 |
3 | import android.graphics.Color;
4 | import android.os.Bundle;
5 | import android.util.Log;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.FrameLayout;
9 |
10 | import androidx.appcompat.app.AppCompatActivity;
11 |
12 | import com.facebook.yoga.YogaEdge;
13 | import com.facebook.yoga.YogaFlexDirection;
14 | import com.facebook.yoga.YogaNode;
15 | import com.facebook.yoga.YogaNodeJNIFinalizer;
16 |
17 | import java.util.ArrayList;
18 |
19 | import javax.annotation.Nullable;
20 |
21 | public class YogaActivity1 extends AppCompatActivity {
22 | private static final int VIEW_WIDTH = 200;
23 |
24 | private float screenHeight;
25 | private float screenWidth;
26 |
27 | private ArrayList poolView = new ArrayList<>();
28 | private ArrayList poolNode = new ArrayList<>();
29 |
30 | private String[][] colors = new String[][] {
31 | new String[] { "#d50000", "#ff1744", "#ff5252", "#ff8a80" },
32 | new String[] { "#c51162", "#f50057", "#ff4081", "#ff80ab" },
33 | new String[] { "#aa00ff", "#d500f9", "#e040fb", "#ea80fc" },
34 | new String[] { "#6200ea", "#651fff", "#7c4dff", "#b388ff" }
35 | };
36 |
37 | @Override
38 | protected void onCreate(@Nullable Bundle savedInstanceState) {
39 | super.onCreate(savedInstanceState);
40 |
41 | FrameLayout container = new FrameLayout(this);
42 |
43 | screenWidth = getWindowManager().getDefaultDisplay().getWidth();
44 | screenHeight = getWindowManager().getDefaultDisplay().getHeight();
45 | log("Screen size = (%f, %f)", screenWidth, screenHeight);
46 |
47 | YogaNode root = new YogaNodeJNIFinalizer();
48 | root.setWidth(screenWidth);
49 | root.setHeight(screenHeight);
50 | root.setFlexDirection(YogaFlexDirection.COLUMN);
51 |
52 | log("start");
53 | createRow1(root, 0);
54 | createRow1(root, 1);
55 | createRow1(root, 2);
56 | createRow1(root, 3);
57 |
58 | root.calculateLayout(screenWidth, screenHeight);
59 |
60 | for (int i = 0; i < poolView.size(); i++) {
61 | View v = poolView.get(i);
62 | YogaNode n = poolNode.get(i);
63 | YogaNode r = n.getOwner();
64 | v.setX(r.getLayoutX() + n.getLayoutX());
65 | v.setY(r.getLayoutY() + n.getLayoutY());
66 | log("v%d position=(%f, %f)",
67 | i,
68 | r.getLayoutX() + n.getLayoutX(),
69 | r.getLayoutY() + n.getLayoutY());
70 | container.addView(v);
71 | }
72 |
73 | log("end");
74 |
75 | setContentView(container);
76 | }
77 |
78 | private void createRow1(YogaNode root, int index) {
79 | log("create index = " + index);
80 | YogaNode row = new YogaNodeJNIFinalizer();
81 | row.setHeight(VIEW_WIDTH);
82 | row.setWidth(VIEW_WIDTH * 4);
83 | row.setFlexDirection(YogaFlexDirection.ROW);
84 | row.setMargin(YogaEdge.ALL, 20);
85 |
86 | for (int i = 0; i < 4; i++) {
87 | YogaNode n = new YogaNodeJNIFinalizer();
88 | n.setWidth(VIEW_WIDTH);
89 | n.setHeight(VIEW_WIDTH);
90 | View v = createView(colors[index][i]);
91 | row.addChildAt(n, i);
92 | poolNode.add(n);
93 | poolView.add(v);
94 | }
95 |
96 | root.addChildAt(row, index);
97 | }
98 |
99 | private View createView(String color) {
100 | View v = new View(this);
101 | v.setBackgroundColor(Color.parseColor(color));
102 | ViewGroup.LayoutParams lp = new FrameLayout.LayoutParams(VIEW_WIDTH, VIEW_WIDTH);
103 | v.setLayoutParams(lp);
104 | return v;
105 | }
106 |
107 | private void log(String template, Object... objects) {
108 | Log.d("max-yoga", String.format(template, objects));
109 | }
110 | }
--------------------------------------------------------------------------------
/src/pages/demo/meituan/home/MTHomeScene.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { TouchableOpacity, Image, Text, StyleSheet, View, FlatList, StatusBar, Linking } from 'react-native';
3 | import { Paragraph, Heading3 } from '../../../../widgets/text/Text';
4 | import screen from '../../../../common/screen';
5 | import NavigationItem from '../../../../widgets/navi/NavigationItem';
6 | import MTAPI from '../common/MTAPI';
7 | import { GroupPurchaseCell } from '../widget/GroupPrchaseCell';
8 | import MTHomeMenuView from './MTHomeMenuView';
9 | import GridView from '../../../../widgets/gridview/GridView';
10 |
11 | const styles = StyleSheet.create({
12 | container: {
13 | flex: 1,
14 | backgroundColor: '#f3f3f3'
15 | },
16 | searchBar: {
17 | width: screen.width * 0.7,
18 | height: 30,
19 | borderRadius: 19,
20 | flexDirection: 'row',
21 | justifyContent: 'center',
22 | alignItems: 'center',
23 | backgroundColor: 'white',
24 | alignSelf: 'center',
25 | },
26 | searchIcon: {
27 | width: 20,
28 | height: 20,
29 | margin: 5,
30 | }
31 | });
32 |
33 | export default class HomeScene extends Component {
34 | static navigationOptions = {
35 | headerTitle: (
36 |
37 |
40 | 搜索
41 |
42 | ),
43 | headerRight: (
44 |
46 | ),
47 | headerLeft: (
48 |
52 | ),
53 | headerStyle: { backgroundColor: '#21C0AE' }
54 | }
55 |
56 | constructor(props) {
57 | super(props);
58 |
59 | this.state = {
60 | discounts: [],
61 | dataList: [],
62 | refreshing: false,
63 | }
64 | }
65 |
66 | componentDidMount() {
67 | this.requestData();
68 | }
69 |
70 | requestData = () => {
71 | this.setState({ refreshing: true });
72 |
73 | this.requestRecommand();
74 | this.requestDiscout();
75 | }
76 |
77 | requestRecommand = async () => {
78 | try {
79 | let response = await fetch(MTAPI.recommend);
80 | let json = await response.json();
81 |
82 | let dataList = json.data.map(info => {
83 | return {
84 | id: info.id,
85 | imageUrl: info.squareimgurl,
86 | title: info.mname,
87 | subtitle: `[${info.range}]${info.title}`,
88 | price: info.price
89 | }
90 | })
91 |
92 | this.setState({
93 | dataList: dataList,
94 | refreshing: false
95 | })
96 | } catch (error) {
97 | this.setState({ refreshing: false })
98 | }
99 | }
100 |
101 | requestDiscout = async () => {
102 | try {
103 | let json = MTAPI.discount;
104 | this.setState({ discounts: json.data })
105 | } catch (error) {
106 | alert(error)
107 | }
108 | }
109 |
110 | renderCell = (info) => {
111 | return (
112 |
115 | )
116 | }
117 |
118 | onCellSelected = (info) => {
119 | StatusBar.setBarStyle('default', false);
120 |
121 | }
122 |
123 | keyExtractor = (item, index) => {
124 | return item.id.toString();
125 | }
126 |
127 | renderHeader = () => {
128 | return (
129 |
130 | Linking.openURL("https://github.com/huanxsd/MeiTuan")}>
132 | 本高仿美团项目代码来源自 huanxsd/MeiTuan
138 |
139 |
140 |
141 |
142 |
143 |
144 | 猜你喜欢
145 |
146 |
147 | )
148 | }
149 |
150 |
151 | render() {
152 | return (
153 |
154 |
160 |
161 | )
162 | }
163 | }
--------------------------------------------------------------------------------
/src/pages/demo/meituan/mine/MTMineScene.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { View, StyleSheet, ScrollView, RefreshControl, Text, Image } from 'react-native';
3 | import NavigationItem from '../../../../widgets/navi/NavigationItem';
4 | import screen from '../../../../common/screen';
5 | import DetailCell from './MTDetailCell';
6 | import { Heading2, Paragraph } from '../../../../widgets/text/Text';
7 |
8 | const styles = StyleSheet.create({
9 | icon: {
10 | width: 27,
11 | height: 27,
12 | },
13 | header: {
14 | backgroundColor: "#21C0AE",
15 | paddingBottom: 20,
16 | flexDirection: 'row',
17 | alignItems: 'center',
18 | margin: 10,
19 | },
20 | avatar: {
21 | width: 50,
22 | height: 50,
23 | marginRight: 10,
24 | borderRadius: 25,
25 | borderWidth: 2,
26 | borderColor: '#51D3C6'
27 | }
28 | })
29 |
30 | export class MTMineScene extends Component {
31 | static navigationOptions = {
32 | headerRight: (
33 |
34 |
36 |
38 |
39 | ),
40 | headerStyle: {
41 | backgroundColor: "#21C0AE",
42 | elevation: 0,
43 | borderBottomWidth: 0
44 | }
45 | }
46 |
47 | constructor(props) {
48 | super(props);
49 |
50 | this.state = {
51 | isRefreshing: false
52 | }
53 | }
54 |
55 | onHeaderRefresh() {
56 | this.setState({ isRefreshing: true});
57 |
58 | setTimeout(() => {
59 | this.setState({ isRefreshing: false})
60 | }, 2000);
61 | }
62 |
63 | renderCells() {
64 | let cells = []
65 | let dataList = this.getDataList();
66 | dataList.forEach((l, index) => {
67 | l.forEach(data => {
68 | cells.push()
73 | })
74 | cells.push()
75 | })
76 | return cells;
77 | }
78 |
79 | renderHeader() {
80 | return (
81 |
82 |
83 |
84 |
85 | Maxiee
86 |
87 |
88 | 个人信息 >
89 |
90 |
91 | )
92 | }
93 |
94 | render() {
95 | return (
96 |
97 |
103 | this.onHeaderRefresh()}
108 | tintColor='gray' />
109 | }>
110 | {this.renderHeader()}
111 |
112 | {this.renderCells()}
113 |
114 |
115 | )
116 | }
117 |
118 | getDataList() {
119 | return (
120 | [
121 | [
122 | { title: '我的钱包', subtitle: '办信用卡', image: require('../img/mine/icon_mine_wallet.png') },
123 | { title: '余额', subtitle: '¥95872385', image: require('../img/mine/icon_mine_balance.png') },
124 | { title: '抵用券', subtitle: '63', image: require('../img/mine/icon_mine_voucher.png') },
125 | { title: '会员卡', subtitle: '2', image: require('../img/mine/icon_mine_membercard.png') }
126 | ],
127 | [
128 | { title: '好友去哪', image: require('../img/mine/icon_mine_friends.png') },
129 | { title: '我的评价', image: require('../img/mine/icon_mine_comment.png') },
130 | { title: '我的收藏', image: require('../img/mine/icon_mine_collection.png') },
131 | { title: '会员中心', subtitle: 'v15', image: require('../img/mine/icon_mine_membercenter.png') },
132 | { title: '积分商城', subtitle: '好礼已上线', image: require('../img/mine/icon_mine_member.png') }
133 | ],
134 | [
135 | { title: '客服中心', image: require('../img/mine/icon_mine_customerService.png') },
136 | { title: '关于美团', subtitle: '我要合作', image: require('../img/mine/icon_mine_aboutmeituan.png') }
137 | ]
138 | ]
139 | )
140 | }
141 | }
--------------------------------------------------------------------------------
/src/pages/demo/twitter/TwitterHome.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 |
3 | import Icon from 'react-native-vector-icons/Ionicons';
4 | import { Animated, StyleSheet, View, Text, Easing } from 'react-native';
5 | import { FacebookTabBar } from './TwitterTab';
6 | import TwitterPost from './TwitterPost';
7 | import screen from '../../../common/screen';
8 | import ScrollableTabView from 'react-native-scrollable-tab-view';
9 |
10 | const AnimatedIcon = Animated.createAnimatedComponent(Icon);
11 |
12 | const styles = StyleSheet.create({
13 | navAndroid: {
14 | backgroundColor: '#3195d7',
15 | width: screen.width,
16 | height: 55,
17 | flexDirection: 'row',
18 | justifyContent: 'space-between',
19 | paddingTop: 15,
20 | paddingLeft: 20,
21 | paddingRight: 10,
22 | },
23 | logoContainer: {
24 | flexDirection: 'row',
25 | justifyContent: 'flex-start'
26 | },
27 | })
28 |
29 | class Entrance extends Component {
30 | constructor(props) {
31 | super(props);
32 | this.state = {
33 | transformAnim: new Animated.Value(1),
34 | opacityAnim: new Animated.Value(1),
35 | }
36 | }
37 |
38 | componentDidMount() {
39 | Animated.timing(
40 | this.state.transformAnim,
41 | {
42 | toValue: 50,
43 | duration: 1200,
44 | delay: 2000,
45 | easing: Easing.elastic(2)
46 | }
47 | ).start();
48 | Animated.timing(
49 | this.state.opacityAnim,
50 | {
51 | toValue: 0,
52 | duration: 800,
53 | easing: Easing.elastic(1),
54 | delay: 2200
55 | }
56 | ).start();
57 | setTimeout(() => {
58 | this.props.hideThis();
59 | }, 3300);
60 | }
61 |
62 | render() {
63 | return (
64 |
74 |
84 |
85 | )
86 | }
87 |
88 | }
89 |
90 | export default class TwitterTab extends Component {
91 | static navigationOptions = {
92 | header: null
93 | }
94 |
95 | constructor(props) {
96 | super(props);
97 | this.state = {
98 | selectedTab: '主页',
99 | title: "主页",
100 | show: true
101 | };
102 | }
103 |
104 | changeTab(tabName) {
105 | this.setState({
106 | selectedTab: tabName
107 | });
108 | }
109 |
110 | updateTitle(obj) {
111 | const {i} = obj;
112 | let title = "";
113 | switch(i) {
114 | case 0:
115 | title = "主页";
116 | break;
117 | case 1:
118 | title = "通知";
119 | break;
120 | case 2:
121 | title = "私信";
122 | break;
123 | case 3:
124 | title = "我";
125 | break;
126 | }
127 | this.setState({
128 | title
129 | });
130 | }
131 |
132 | render() {
133 | let entrance = this.state.show ? this.setState({show: false})} /> :
134 | return (
135 |
136 |
137 |
138 |
139 |
140 | Twitter
141 |
142 |
143 |
144 |
145 |
146 |
147 | this.updateTitle(obj)}
149 | tabBarPosition='bottom'
150 | renderTabBar={() => null}/>}>
151 |
152 |
153 |
154 |
155 |
156 |
157 | {entrance}
158 |
159 | )
160 | }
161 | }
--------------------------------------------------------------------------------
/ios/MaxieeRNLab.xcodeproj/xcshareddata/xcschemes/MaxieeRNLab.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
43 |
49 |
50 |
51 |
52 |
53 |
58 |
59 |
61 |
67 |
68 |
69 |
70 |
71 |
77 |
78 |
79 |
80 |
81 |
82 |
92 |
94 |
100 |
101 |
102 |
103 |
104 |
105 |
111 |
113 |
119 |
120 |
121 |
122 |
124 |
125 |
128 |
129 |
130 |
--------------------------------------------------------------------------------
/ios/MaxieeRNLab.xcodeproj/xcshareddata/xcschemes/MaxieeRNLab-tvOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
43 |
49 |
50 |
51 |
52 |
53 |
58 |
59 |
61 |
67 |
68 |
69 |
70 |
71 |
77 |
78 |
79 |
80 |
81 |
82 |
92 |
94 |
100 |
101 |
102 |
103 |
104 |
105 |
111 |
113 |
119 |
120 |
121 |
122 |
124 |
125 |
128 |
129 |
130 |
--------------------------------------------------------------------------------
/src/pages/home/HomeBasic.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import { View, ScrollView } from 'react-native';
3 | import Icon from 'react-native-vector-icons/Ionicons';
4 | import IntentLauncher from 'react-native-intent-launcher';
5 | import GridView from '../../widgets/gridview/GridView';
6 | import { createHeader } from '../../common/utils/HomeUtils';
7 |
8 | export default class HomeUsage extends React.Component {
9 | static navigationOptions = {
10 | title: 'Basic'
11 | }
12 |
13 | render() {
14 | let infosYoga = [
15 | {
16 | title: "Simple Demo",
17 | subtitle: "layouting 3 views",
18 | onPress: () => IntentLauncher.startActivity({
19 | className: 'com.maxieernlab.yoga.YogaActivity2'
20 | })
21 | }, {
22 | title: "Complex Demo",
23 | subtitle: "layouting 16 views",
24 | onPress: () => IntentLauncher.startActivity({
25 | className: 'com.maxieernlab.yoga.YogaActivity1'
26 | })
27 | },
28 | ];
29 |
30 | let infosWidgets = [
31 | {
32 | title: "Buttons",
33 | icon: ,
34 | subtitle: "",
35 | onPress: () => this.props.navigation.navigate("DemoButton")
36 | },
37 | {
38 | title: "CheckBoxes",
39 | icon: ,
40 | subtitle: "",
41 | onPress: () => this.props.navigation.navigate("DemoCheckBoxes")
42 | },
43 | {
44 | title: "Simple View",
45 | icon: ,
46 | subtitle: "",
47 | onPress: () => this.props.navigation.navigate("DemoSimpleView")
48 | },
49 | {
50 | title: "Image",
51 | icon: ,
52 | subtitle: "",
53 | onPress: () => this.props.navigation.navigate("ReactNativeUIImage")
54 | },
55 | {
56 | title: "ScrollView",
57 | icon: ,
58 | subtitle: "",
59 | onPress: () => this.props.navigation.navigate("RNBasicScrollView")
60 | }
61 | ];
62 |
63 | let infosThirdParty = [
64 | {
65 | title: 'react-native-swiper',
66 | subtitle: '',
67 | icon: ,
68 | onPress: () => this.props.navigation.navigate("RNThirdSwiper")
69 | },
70 | {
71 | title: 'react-native-scrollable-tab-view',
72 | subtitle: '',
73 | icon: ,
74 | onPress: () => this.props.navigation.navigate("RNScrollableTabView")
75 | }
76 | ]
77 |
78 | let infosReactNavigation = [
79 | {
80 | title: "Simple Stack",
81 | subtitle: "",
82 | icon: ,
83 | onPress: () => this.props.navigation.navigate("StackDemo")
84 | },
85 | {
86 | title: "Custom Header",
87 | subtitle: "",
88 | icon: ,
89 | onPress: () => this.props.navigation.navigate("CustomHeader")
90 | },
91 | ]
92 |
93 | let infosTemplate = [
94 | {
95 | title: "Login Demo 1",
96 | subtitle: "",
97 | onPress: () => this.props.navigation.navigate("DemoLogin1")
98 | }
99 | ]
100 |
101 | return (
102 |
103 | {createHeader("Yoga Demo")}
104 | infosYoga[index].onPress()} />
107 |
108 | {createHeader("RN Widgets")}
109 | infosWidgets[index].onPress()} />
112 |
113 | {createHeader("3rd Party Widgets")}
114 | infosThirdParty[index].onPress()} />
117 |
118 | {createHeader("React Navigation")}
119 | infosReactNavigation[index].onPress()} />
122 |
123 | {createHeader("Template Page")}
124 | infosTemplate[index].onPress()} />
127 | {/*
128 | // this.createHeader("React Navigation"),
129 | // this.createLink("HeartBeat BottomNavigation 1", "HeartBeatBottomNavi"),
130 | // this.createLink("Material Top Navigation", "NavigationHello"),
131 | // this.createHeader("Redux"),
132 | // this.createLink("Redux Todo Demo", "ReduxTodo"),
133 | // this.createHeader("IM"),
134 | // this.createLink("Gifted Chat Demo", "ChatDemo"),
135 | // this.createHeader("Chart"),
136 | // this.createLink("Line Chart Demo", "DemoLineChart") */}
137 | )
138 | }
139 | }
--------------------------------------------------------------------------------
/src/pages/basic/RNThirdSwiper.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Text, View, ScrollView, StyleSheet, Button, Image } from 'react-native';
3 | import Swiper from 'react-native-swiper'
4 | import { createStackNavigator } from '@react-navigation/stack';
5 | import GridView from '../../widgets/gridview/GridView';
6 | import Icon from 'react-native-vector-icons/Ionicons';
7 |
8 | const styles = StyleSheet.create({
9 | slide1: {
10 | flex: 1,
11 | justifyContent: 'center',
12 | alignItems: 'center',
13 | backgroundColor: '#9DD6EB'
14 | },
15 | slide2: {
16 | flex: 1,
17 | justifyContent: 'center',
18 | alignItems: 'center',
19 | backgroundColor: '#97CAE5'
20 | },
21 | slide3: {
22 | flex: 1,
23 | justifyContent: 'center',
24 | alignItems: 'center',
25 | backgroundColor: '#92BBD9'
26 | },
27 | text: {
28 | color: '#fff',
29 | fontSize: 30,
30 | fontWeight: 'bold'
31 | },
32 | slide: {
33 | flex: 1,
34 | justifyContent: 'center',
35 | alignItems: 'center',
36 | },
37 | })
38 |
39 | const BasicDemo = () => {
40 | return (
41 |
42 |
43 | Hello Swiper
44 |
45 |
46 | Beautiful
47 |
48 |
49 | And simple
50 |
51 |
52 | )
53 | }
54 |
55 | const VerticalDemo = () => {
56 | return (
57 |
58 |
59 | Hello Swiper
60 |
61 |
62 | Beautiful
63 |
64 |
65 | And simple
66 |
67 |
68 | )
69 | }
70 |
71 | const ImageDemo = () => {
72 | return (
73 |
74 |
83 | }
84 | activeDot={
85 |
92 | }
93 | paginationStyle={{
94 | bottom: -23,
95 | left: null,
96 | right: 10
97 | }}>
98 | Aussie tourist dies at Bali hotel}>
99 |
100 |
101 | Big lie behind Nine’s new show}>
102 |
103 |
104 | Why Stone split from Garfield}>
105 |
106 |
107 | Learn from Kim K to land that job}>
108 |
109 |
110 |
111 |
112 | )
113 | }
114 |
115 | const HomeDemo = (props) => {
116 | let infos = [
117 | {
118 | title: "Basic",
119 | subtitle: "",
120 | icon: ,
121 | onPress: () => props.navigation.push('Basic')
122 | },
123 | {
124 | title: "Vertical",
125 | subtitle: "autoplay",
126 | icon: ,
127 | onPress: () => props.navigation.push('Vertical')
128 | },
129 | {
130 | title: "Image",
131 | subtitle: "",
132 | icon: ,
133 | onPress: () => props.navigation.push('Image')
134 | },
135 | ];
136 |
137 | return (
138 |
139 | infos[index].onPress()}/>
142 |
143 | )
144 | }
145 |
146 | const Stack = createStackNavigator();
147 |
148 | export default () => {
149 | return (
150 |
151 |
154 |
157 |
160 |
163 |
164 | )
165 | }
166 |
167 | // const Stack = createStackNavigator({
168 | // Home: HomeDemo,
169 | // Basic: BasicDemo,
170 | // Vertical: VerticalDemo,
171 | // Image: ImageDemo
172 | // }, {
173 | // headerMode: "none"
174 | // });
175 |
176 | // export default Stack;
--------------------------------------------------------------------------------
/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 | # Determine the Java command to use to start the JVM.
86 | if [ -n "$JAVA_HOME" ] ; then
87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
88 | # IBM's JDK on AIX uses strange locations for the executables
89 | JAVACMD="$JAVA_HOME/jre/sh/java"
90 | else
91 | JAVACMD="$JAVA_HOME/bin/java"
92 | fi
93 | if [ ! -x "$JAVACMD" ] ; then
94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
95 |
96 | Please set the JAVA_HOME variable in your environment to match the
97 | location of your Java installation."
98 | fi
99 | else
100 | JAVACMD="java"
101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
102 |
103 | Please set the JAVA_HOME variable in your environment to match the
104 | location of your Java installation."
105 | fi
106 |
107 | # Increase the maximum file descriptors if we can.
108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
109 | MAX_FD_LIMIT=`ulimit -H -n`
110 | if [ $? -eq 0 ] ; then
111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
112 | MAX_FD="$MAX_FD_LIMIT"
113 | fi
114 | ulimit -n $MAX_FD
115 | if [ $? -ne 0 ] ; then
116 | warn "Could not set maximum file descriptor limit: $MAX_FD"
117 | fi
118 | else
119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
120 | fi
121 | fi
122 |
123 | # For Darwin, add options to specify how the application appears in the dock
124 | if $darwin; then
125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
126 | fi
127 |
128 | # For Cygwin, switch paths to Windows format before running java
129 | if $cygwin ; then
130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
132 | JAVACMD=`cygpath --unix "$JAVACMD"`
133 |
134 | # We build the pattern for arguments to be converted via cygpath
135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
136 | SEP=""
137 | for dir in $ROOTDIRSRAW ; do
138 | ROOTDIRS="$ROOTDIRS$SEP$dir"
139 | SEP="|"
140 | done
141 | OURCYGPATTERN="(^($ROOTDIRS))"
142 | # Add a user-defined pattern to the cygpath arguments
143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
145 | fi
146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
147 | i=0
148 | for arg in "$@" ; do
149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
151 |
152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
154 | else
155 | eval `echo args$i`="\"$arg\""
156 | fi
157 | i=$((i+1))
158 | done
159 | case $i in
160 | (0) set -- ;;
161 | (1) set -- "$args0" ;;
162 | (2) set -- "$args0" "$args1" ;;
163 | (3) set -- "$args0" "$args1" "$args2" ;;
164 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
165 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
166 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
167 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
168 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
169 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
170 | esac
171 | fi
172 |
173 | # Escape application args
174 | save () {
175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
176 | echo " "
177 | }
178 | APP_ARGS=$(save "$@")
179 |
180 | # Collect all arguments for the java command, following the shell quoting and substitution rules
181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
182 |
183 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
184 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
185 | cd "$(dirname "$0")"
186 | fi
187 |
188 | exec "$JAVACMD" "$@"
189 |
--------------------------------------------------------------------------------
/src/pages/home/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import { NavigationContainer } from '@react-navigation/native';
3 | import { createStackNavigator } from '@react-navigation/stack';
4 | import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
5 | import HomeBasic from './HomeBasic';
6 | import DemoSimpleView from '../../demo/ReactNativeUIDemo/DemoSimpleView';
7 | import DemoButton from '../../demo/ReactNativeUIDemo/DemoButton';
8 | import DemoLogin1 from '../../demo/LoginDemo/DemoLogin1';
9 | import ChatDemo from '../../demo/ChatDemo';
10 | import DemoLineChart from '../../demo/ChartDemo/DemoLineChart';
11 | import NavigationHello from '../../demo/NavigationDemo/NavigationHello';
12 | import StackDemo from '../../demo/NavigationDemo/StackDemo'
13 | import HeartBeatBottomNavi from '../../demo/NavigationDemo/Custom/BottomNavigation/HeartBeatBottomNavi';
14 | import ReactNativeUIImage from '../../demo/ReactNativeUIDemo/demos/ReactNativeUIImage';
15 | import ReduxTodo from '../../demo/ReduxDemo/demos/ReduxTodo'
16 | import TemplateHome from '../template/TemplateHome';
17 | import DemoHome from '../demo/DemoHome';
18 | // Demos
19 | import MeituanHome from '../demo/meituan/MeituanHome';
20 | import RNBasicScrollView from '../basic/RNBasicScrollView';
21 | import RNThirdSwiper from '../basic/RNThirdSwiper';
22 | import StopWatchHome from '../demo/StopWatch/StopWatchHome';
23 | import WeatherHome from '../demo/weather/WeatherHome';
24 | import TwitterHome from '../demo/twitter/TwitterHome';
25 | import RNScrollableTabView from '../basic/RNScrollableTabView';
26 | import MyLocationHome from '../demo/mylocation/MyLocationHome';
27 | import CustomHeader from '../../demo/NavigationDemo/CustomHeader';
28 |
29 | // const Tab = createBottomTabNavigator({
30 | // Home: {
31 | // screen: createStackNavigator({Home: HomeBasic}),
32 | // navigationOptions: {
33 | // tabBarLabel: 'Basic'
34 | // }
35 | // },
36 | // Template: {
37 | // screen: createStackNavigator({Template: TemplateHome}),
38 | // navigationOptions: {
39 | // tabBarLabel: 'Template'
40 | // }
41 | // },
42 | // Demo: {
43 | // screen: createStackNavigator({Demo: DemoHome}),
44 | // navigationOptions: {
45 | // tabBarLabel: 'Demo'
46 | // }
47 | // }
48 | // });
49 |
50 | // Tab.navigationOptions = {
51 | // header: null
52 | // }
53 |
54 | // const AppNavigator = createStackNavigator({
55 | // Tab: { screen: Tab },
56 | // DemoSimpleView: DemoSimpleView,
57 | // // React Navigation
58 | // NavigationHello: NavigationHello,
59 | // StackDemo: StackDemo,
60 | // CustomHeader: CustomHeader,
61 | // HeartBeatBottomNavi: HeartBeatBottomNavi,
62 | // ReactNativeUIImage: ReactNativeUIImage,
63 | // // Redux Demo
64 | // ReduxTodo: ReduxTodo,
65 | // DemoButton: DemoButton,
66 | // DemoLogin1: DemoLogin1,
67 | // // Chat Demo
68 | // ChatDemo: ChatDemo,
69 | // // Charts
70 | // DemoLineChart: DemoLineChart,
71 | // // Demos
72 | // MeituanHome: MeituanHome,
73 | // StopWatch: StopWatchHome,
74 | // Weather: WeatherHome,
75 | // Twitter: TwitterHome,
76 | // // RN Basic
77 | // RNBasicScrollView: RNBasicScrollView,
78 | // RNScrollableTabView: RNScrollableTabView,
79 | // // Third Party Widgets
80 | // RNThirdSwiper: RNThirdSwiper,
81 | // MyLocation: MyLocationHome,
82 |
83 | // }, {
84 | // defaultNavigationOptions: {
85 | // headerBackTitle: null,
86 | // headerTintColor: '#333333',
87 | // showIcon: true,
88 | // }
89 | // });
90 |
91 | // const AppContainer = createAppContainer(AppNavigator);
92 |
93 | const Stack = createStackNavigator();
94 | const Tab = createBottomTabNavigator();
95 |
96 | const HomeTabs = () => {
97 | return (
98 |
99 |
102 |
105 |
108 |
109 | )
110 | }
111 |
112 | class HomePage extends React.Component {
113 |
114 | render() {
115 | return
116 |
118 |
121 |
124 |
127 |
130 |
133 |
136 |
139 |
142 |
145 |
148 |
151 |
154 |
157 |
160 |
163 |
166 |
169 |
172 |
175 |
178 |
179 |
180 | }
181 | }
182 |
183 | export default HomePage;
--------------------------------------------------------------------------------
/src/pages/demo/meituan/common/MTAPI.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Liu Jinyong
3 | * All rights reserved.
4 | *
5 | * https://github.com/huanxsd/MeiTuan
6 | * @flow
7 | */
8 |
9 |
10 | export default {
11 | recommend: 'http://api.meituan.com/group/v1/recommend/homepage/city/1?__skck=40aaaf01c2fc4801b9c059efcd7aa146&__skcy=mrUZYo7999nH8WgTicdfzaGjaSQ=&__skno=51156DC4-B59A-4108-8812-AD05BF227A47&__skts=1434530933.303717&__skua=bd6b6e8eadfad15571a15c3b9ef9199a&__vhost=api.mobile.meituan.com&ci=1&client=iphone&limit=40&movieBundleVersion=100&msid=48E2B810-805D-4821-9CDD-D5C9E01BC98A2015-06-17-14-50363&offset=0&position=39.983497,116.318042&userId=10086&userid=10086&utm_campaign=AgroupBgroupD100Fab_chunceshishuju__a__a___b1junglehomepagecatesort__b__leftflow___ab_gxhceshi__nostrategy__leftflow___ab_gxhceshi0202__b__a___ab_pindaochangsha__a__leftflow___ab_xinkeceshi__b__leftflow___ab_gxtest__gd__leftflow___ab_gxh_82__nostrategy__leftflow___ab_pindaoshenyang__a__leftflow___i_group_5_2_deallist_poitype__d__d___ab_b_food_57_purepoilist_extinfo__a__a___ab_trip_yidizhoubianyou__b__leftflow___ab_i_group_5_3_poidetaildeallist__a__b___ab_waimaizhanshi__b__b1___a20141120nanning__m1__leftflow___ab_pind',
12 |
13 |
14 |
15 | discount: {
16 | "stid": "836121754643660800",
17 | "data": [
18 | { "typeface_color": "#ff9900", "position": 0, "module": false, "maintitle": "莫莉幻想", "type": 1, "deputytitle": "5人行4人免", "solds": 0, "id": 6156, "share": { "message": "莫莉幻想优惠来袭", "url": "http%3A%2F%2Fi.meituan.com%2Ffirework%2Fpd1490755747%3F" }, "title": "莫莉幻想", "deputy_typeface_color": "#21c0ae", "tplurl": "imeituan://www.meituan.com/web?url=http://i.meituan.com/firework/ox1491533539", "imageurl": require('../img/home/icon_homepage_food_category.png') },
19 | { "typeface_color": "#f6687d", "position": 0, "module": false, "maintitle": "大片特惠", "type": 1, "deputytitle": "速度与激情8", "solds": 0, "id": 6121, "share": { "message": "热门大片特惠,福利再来一波>>", "url": "http://i.meituan.com/firework/ox1491533539" }, "title": "大片特惠", "deputy_typeface_color": "#c280fc", "tplurl": "imeituan://www.meituan.com/web?url=http://i.meituan.com/firework/ox1491533539", "imageurl": require('../img/home/icon_homepage_food_category.png') },
20 | { "typeface_color": "#6bbd00", "position": 0, "module": false, "maintitle": "清仓特价", "type": 1, "deputytitle": "1元巴厘岛", "solds": 0, "id": 6140, "share": { "message": "清仓特价,1元巴厘岛", "url": "http%3a%2f%2fi.meituan.com%2ffirework%2foverseaWeekend" }, "title": "清仓特价", "deputy_typeface_color": "#fc6a56", "tplurl": "imeituan://www.meituan.com/web?url=http://i.meituan.com/firework/ox1491533539", "imageurl": require('../img/home/icon_homepage_food_category.png') },
21 | { "typeface_color": "#06c1ae", "position": 0, "module": false, "maintitle": "今日推荐", "type": 1, "deputytitle": "品质生活指南", "solds": 0, "id": 3283, "share": { "message": "吃喝玩乐全都有,尽在美团网!", "url": "http://api.mobile.meituan.com/group/v1/re/p" }, "title": "今日推荐", "deputy_typeface_color": "#fdb32b", "tplurl": "imeituan://www.meituan.com/web?url=http://i.meituan.com/firework/ox1491533539", "imageurl": require('../img/home/icon_homepage_food_category.png') }
22 | ], "server": { "time": 1492267134 }, "paging": { "count": 4 } },
23 |
24 |
25 | menuInfo: [
26 | { title: '美食', icon: require('../img/home/icon_homepage_food_category.png') },
27 | { title: '电影', icon: require('../img/home/icon_homepage_movie_category.png') },
28 | { title: '酒店', icon: require('../img/home/icon_homepage_hotel_category.png') },
29 | { title: 'KTV', icon: require('../img/home/icon_homepage_ktv_category.png') },
30 | { title: '优惠买单', icon: require('../img/home/icon_homepage_default.png') },
31 | { title: '周边游', icon: require('../img/home/icon_homepage_foottreat_category.png') },
32 | { title: '生活服务', icon: require('../img/home/icon_homepage_life_service_category.png') },
33 | { title: '休闲娱乐', icon: require('../img/home/icon_homepage_entertainment_category.png') },
34 | { title: '丽人/美发', icon: require('../img/home/icon_homepage_beauty_category.png') },
35 | { title: '购物', icon: require('../img/home/icon_homepage_shopping_category.png') },
36 |
37 | { title: '丽人/美发', icon: require('../img/home/icon_homepage_beauty_category.png') },
38 | { title: '电影', icon: require('../img/home/icon_homepage_movie_category.png') },
39 | { title: '周边游', icon: require('../img/home/icon_homepage_foottreat_category.png') },
40 | { title: '酒店', icon: require('../img/home/icon_homepage_hotel_category.png') },
41 | { title: '优惠买单', icon: require('../img/home/icon_homepage_default.png') },
42 | { title: '休闲娱乐', icon: require('../img/home/icon_homepage_entertainment_category.png') },
43 | { title: 'KTV', icon: require('../img/home/icon_homepage_ktv_category.png') },
44 | ]
45 | }
46 |
47 | export function recommendUrlWithId(id) {
48 | return 'http://api.meituan.com/group/v1/deal/recommend/collaborative?__skck=40aaaf01c2fc4801b9c059efcd7aa146&__skcy=hWCwhGYpNTG7TjXWHOwPykgoKX0%3D&__skno=433ACF85-E134-4FEC-94B5-DA35D33AC753&__skts=1436343274.685593&__skua=bd6b6e8eadfad15571a15c3b9ef9199a&__vhost=api.mobile.meituan.com&cate=0&ci=1&cityId=1&client=iphone&did=' + id + '&district=-1&fields=id%2Cslug%2Cimgurl%2Cprice%2Ctitle%2Cbrandname%2Crange%2Cvalue%2Cmlls%2Csolds&hasbuy=0&latlng=0.000000%2C0.000000&movieBundleVersion=100&msid=48E2B810-805D-4821-9CDD-D5C9E01BC98A2015-07-08-15-36746&offset=0&scene=view-v4&userId=10086&userid=10086&utm_campaign=AgroupBgroupD100Fab_i550poi_ktv__d__j___ab_i_group_5_3_poidetaildeallist__a__b___ab_gxhceshi0202__b__a___ab_pindaoquxincelue0630__b__b1___ab_i_group_5_6_searchkuang__a__leftflow___i_group_5_2_deallist_poitype__d__d___ab_i550poi_xxyl__b__leftflow___ab_b_food_57_purepoilist_extinfo__a__a___ab_waimaiwending__a__a___ab_waimaizhanshi__b__b1___ab_i550poi_lr__d__leftflow___ab_i_group_5_5_onsite__b__b___ab_xinkeceshi__b__leftflowGhomepage_guess_27774127&utm_content=4B8C0B46F5B0527D55EA292904FD7E12E48FB7BEA8DF50BFE7828AF7F20BB08D&utm_medium=iphone&utm_source=AppStore&utm_term=5.7&uuid=4B8C0B46F5B0527D55EA292904FD7E12E48FB7BEA8DF50BFE7828AF7F20BB08D&version_name=5.7'
49 | }
50 |
51 |
52 | export function groupPurchaseDetailWithId(id) {
53 | return 'http://api.meituan.com/group/v1/deal/list/id/' + id + '?__skck=40aaaf01c2fc4801b9c059efcd7aa146&__skcy=4NDQ%2BojQ%2BZGArOWQCEgWI19Pzus%3D&__skno=803C28CE-8BA8-4831-B2DE-7BCD484348D9&__skts=1435888257.411030&__skua=bd6b6e8eadfad15571a15c3b9ef9199a&__vhost=api.mobile.meituan.com&ci=1&client=iphone&movieBundleVersion=100&msid=48E2B810-805D-4821-9CDD-D5C9E01BC98A2015-07-03-09-14430&userid=10086&utm_campaign=AgroupBgroupC1080988208017226240_c0_e68cafa9e104898bb8bfcd78b64aef671D100Fab_i_group_5_3_poidetaildeallist__a__b___ab_chunceshishuju__a__a___ab_gxhceshi__nostrategy__leftflow___ab_gxhceshi0202__b__a___ab_pindaochangsha__a__leftflow___ab_xinkeceshi__b__leftflow___ab_gxtest__gd__leftflow___ab_waimaiwending__a__a___ab_gxh_82__nostrategy__leftflow___i_group_5_2_deallist_poitype__d__d___ab_b_food_57_purepoilist_extinfo__a__a___ab_pindaoshenyang__a__leftflow___ab_pindaoquxincelue0630__b__b1___ab_waimaizhanshi__b__b1___a20141120nanning__m1__leftflow___b1junglehomepagecatesort__b__leftflow___ab_i_group_5_5_onsite__b__b___ab_i_group_5_6_searchkuang__a__leftflowGhomepage_guess_27774127&utm_content=4B8C0B46F5B0527D55EA292904FD7E12E48FB7BEA8DF50BFE7828AF7F20BB08D&utm_medium=iphone&utm_source=AppStore&utm_term=5.7&uuid=4B8C0B46F5B0527D55EA292904FD7E12E48FB7BEA8DF50BFE7828AF7F20BB08D&version_name=5.7'
54 | }
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "com.android.application"
2 |
3 | import com.android.build.OutputFile
4 |
5 | /**
6 | * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
7 | * and bundleReleaseJsAndAssets).
8 | * These basically call `react-native bundle` with the correct arguments during the Android build
9 | * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
10 | * bundle directly from the development server. Below you can see all the possible configurations
11 | * and their defaults. If you decide to add a configuration block, make sure to add it before the
12 | * `apply from: "../../node_modules/react-native/react.gradle"` line.
13 | *
14 | * project.ext.react = [
15 | * // the name of the generated asset file containing your JS bundle
16 | * bundleAssetName: "index.android.bundle",
17 | *
18 | * // https://facebook.github.io/react-native/docs/performance#enable-the-ram-format
19 | * bundleCommand: "ram-bundle",
20 | *
21 | * // the entry file for bundle generation
22 | * entryFile: "index.android.js",
23 | *
24 | * // whether to bundle JS and assets in debug mode
25 | * bundleInDebug: false,
26 | *
27 | * // whether to bundle JS and assets in release mode
28 | * bundleInRelease: true,
29 | *
30 | * // whether to bundle JS and assets in another build variant (if configured).
31 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
32 | * // The configuration property can be in the following formats
33 | * // 'bundleIn${productFlavor}${buildType}'
34 | * // 'bundleIn${buildType}'
35 | * // bundleInFreeDebug: true,
36 | * // bundleInPaidRelease: true,
37 | * // bundleInBeta: true,
38 | *
39 | * // whether to disable dev mode in custom build variants (by default only disabled in release)
40 | * // for example: to disable dev mode in the staging build type (if configured)
41 | * devDisabledInStaging: true,
42 | * // The configuration property can be in the following formats
43 | * // 'devDisabledIn${productFlavor}${buildType}'
44 | * // 'devDisabledIn${buildType}'
45 | *
46 | * // the root of your project, i.e. where "package.json" lives
47 | * root: "../../",
48 | *
49 | * // where to put the JS bundle asset in debug mode
50 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
51 | *
52 | * // where to put the JS bundle asset in release mode
53 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release",
54 | *
55 | * // where to put drawable resources / React Native assets, e.g. the ones you use via
56 | * // require('./image.png')), in debug mode
57 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
58 | *
59 | * // where to put drawable resources / React Native assets, e.g. the ones you use via
60 | * // require('./image.png')), in release mode
61 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
62 | *
63 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means
64 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
65 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle
66 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
67 | * // for example, you might want to remove it from here.
68 | * inputExcludes: ["android/**", "ios/**"],
69 | *
70 | * // override which node gets called and with what additional arguments
71 | * nodeExecutableAndArgs: ["node"],
72 | *
73 | * // supply additional arguments to the packager
74 | * extraPackagerArgs: []
75 | * ]
76 | */
77 |
78 | project.ext.react = [
79 | entryFile: "index.js",
80 | enableHermes: false, // clean and rebuild if changing
81 | ]
82 |
83 | apply from: "../../node_modules/react-native/react.gradle"
84 |
85 | project.ext.vectoricons = [
86 | iconFontNames: [ 'Ionicons.ttf'] // Name of the font files you want to copy
87 | ]
88 |
89 | apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
90 |
91 | /**
92 | * Set this to true to create two separate APKs instead of one:
93 | * - An APK that only works on ARM devices
94 | * - An APK that only works on x86 devices
95 | * The advantage is the size of the APK is reduced by about 4MB.
96 | * Upload all the APKs to the Play Store and people will download
97 | * the correct one based on the CPU architecture of their device.
98 | */
99 | def enableSeparateBuildPerCPUArchitecture = false
100 |
101 | /**
102 | * Run Proguard to shrink the Java bytecode in release builds.
103 | */
104 | def enableProguardInReleaseBuilds = false
105 |
106 | /**
107 | * The preferred build flavor of JavaScriptCore.
108 | *
109 | * For example, to use the international variant, you can use:
110 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
111 | *
112 | * The international variant includes ICU i18n library and necessary data
113 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
114 | * give correct results when using with locales other than en-US. Note that
115 | * this variant is about 6MiB larger per architecture than default.
116 | */
117 | def jscFlavor = 'org.webkit:android-jsc:+'
118 |
119 | /**
120 | * Whether to enable the Hermes VM.
121 | *
122 | * This should be set on project.ext.react and mirrored here. If it is not set
123 | * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
124 | * and the benefits of using Hermes will therefore be sharply reduced.
125 | */
126 | def enableHermes = project.ext.react.get("enableHermes", false);
127 |
128 | android {
129 | compileSdkVersion rootProject.ext.compileSdkVersion
130 |
131 | compileOptions {
132 | sourceCompatibility JavaVersion.VERSION_1_8
133 | targetCompatibility JavaVersion.VERSION_1_8
134 | }
135 |
136 | defaultConfig {
137 | applicationId "com.maxieernlab"
138 | minSdkVersion rootProject.ext.minSdkVersion
139 | targetSdkVersion rootProject.ext.targetSdkVersion
140 | versionCode 1
141 | versionName "1.0"
142 | }
143 | splits {
144 | abi {
145 | reset()
146 | enable enableSeparateBuildPerCPUArchitecture
147 | universalApk false // If true, also generate a universal APK
148 | include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
149 | }
150 | }
151 |
152 | signingConfigs {
153 | debug {
154 | storeFile file('debug.keystore')
155 | storePassword 'android'
156 | keyAlias 'androiddebugkey'
157 | keyPassword 'android'
158 | }
159 | }
160 |
161 | buildTypes {
162 | debug {
163 | signingConfig signingConfigs.debug
164 | }
165 | release {
166 | // Caution! In production, you need to generate your own keystore file.
167 | // see https://facebook.github.io/react-native/docs/signed-apk-android.
168 | signingConfig signingConfigs.debug
169 | minifyEnabled enableProguardInReleaseBuilds
170 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
171 | }
172 | }
173 | // applicationVariants are e.g. debug, release
174 | applicationVariants.all { variant ->
175 | variant.outputs.each { output ->
176 | // For each separate APK per architecture, set a unique version code as described here:
177 | // https://developer.android.com/studio/build/configure-apk-splits.html
178 | def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
179 | def abi = output.getFilter(OutputFile.ABI)
180 | if (abi != null) { // null for the universal-debug, universal-release variants
181 | output.versionCodeOverride =
182 | versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
183 | }
184 | }
185 | }
186 | }
187 |
188 | dependencies {
189 | implementation fileTree(dir: "libs", include: ["*.jar"])
190 | implementation "com.facebook.react:react-native:+" // From node_modules
191 | if (enableHermes) {
192 | def hermesPath = "../../node_modules/hermes-engine/android/";
193 | debugImplementation files(hermesPath + "hermes-debug.aar")
194 | releaseImplementation files(hermesPath + "hermes-release.aar")
195 | } else {
196 | implementation jscFlavor
197 | }
198 | }
199 |
200 | // Run this once to be able to run the application with _BUCK
201 | // puts all compile dependencies into folder libs for _BUCK to use
202 | task copyDownloadableDepsToLibs(type: Copy) {
203 | from configurations.compile
204 | into 'libs'
205 | }
206 |
207 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
--------------------------------------------------------------------------------
/src/pages/demo/StopWatch/StopWatchHome.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import { View, Text, TouchableHighlight, ListView } from 'react-native';
3 | import screen from '../../../common/screen';
4 |
5 | class WatchFace extends Component {
6 | render() {
7 | return (
8 |
19 | {this.props.sectionTime}
29 | {this.props.totalTime}
35 |
36 | )
37 | }
38 | }
39 |
40 | class WatchControl extends Component {
41 | constructor(props) {
42 | super(props);
43 | this.state = {
44 | watchOn: false,
45 | startBtnText: "启动",
46 | startBtnColor: "#60B644",
47 | stopBtnText: "计次",
48 | underlayColor:"#fff",
49 | }
50 | }
51 |
52 | startWatch() {
53 | console.log("startWatch max")
54 | if (!this.state.watchOn) {
55 | this.props.startWatch();
56 | this.setState({
57 | startBtnText: '停止',
58 | startBtnColor: '#ff0044',
59 | stopBtnText: '计次',
60 | underlayColor: '#eee',
61 | watchOn: true
62 | })
63 | } else {
64 | this.props.stopWatch();
65 | this.setState({
66 | startBtnText: '启动',
67 | startBtnColor: '#60B644',
68 | stopBtnText: '复位',
69 | underlayColor: '#eee',
70 | watchOn: false
71 | })
72 | }
73 | }
74 |
75 | addRecord() {
76 | if (this.state.watchOn) {
77 | this.props.addRecord()
78 | } else {
79 | this.props.clearRecord()
80 | this.setState({
81 | stopBtnText: "计次"
82 | })
83 | }
84 | }
85 |
86 | render() {
87 | return (
88 |
98 |
99 | this.addRecord()}>
108 | {this.state.stopBtnText}
113 |
114 |
115 |
119 | this.startWatch()}>
129 | {this.state.startBtnText}
134 |
135 |
136 |
137 | )
138 | }
139 | }
140 |
141 | class WatchRecord extends Component {
142 | render() {
143 | let ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}),
144 | theDataSource = ds.cloneWithRows(this.props.record);
145 | return (
146 |
154 |
165 | {rowData.title}
172 |
173 | {rowData.time}
180 |
181 |
182 | }/>
183 | )
184 | }
185 | }
186 |
187 | export default class StopWatchHome extends Component {
188 | constructor(props) {
189 | super(props);
190 |
191 | this.state = {
192 | stopWatch: false,
193 | resetWatch: true,
194 | initialTime: 0,
195 | currentTime: 0,
196 | recorderTime: 0,
197 | timeAccumulation: 0,
198 | totalTime: "00:00.00",
199 | sectionTime: "00:00.00",
200 | recordCounter: 0,
201 | record:[
202 | {title:"",time:""},
203 | {title:"",time:""},
204 | {title:"",time:""},
205 | {title:"",time:""},
206 | {title:"",time:""},
207 | {title:"",time:""},
208 | {title:"",time:""}
209 | ],
210 | }
211 | }
212 |
213 | componentWillUnmount() {
214 | this.stopWatch();
215 | this.clearRecord();
216 | }
217 |
218 | startWatch() {
219 | if (this.state.resetWatch) {
220 | this.setState({
221 | stopWatch: false,
222 | resetWatch: false,
223 | timeAccumulation: 0,
224 | initialTime: (new Date()).getTime()
225 | })
226 | } else {
227 | this.setState({
228 | stopWatch: false,
229 | initialTime: (new Date()).getTime()
230 | })
231 | }
232 |
233 | let milSecond, second, minute, countingTime, secmilSecond, secsecond, secminute, seccountingTime;
234 | let interval = setInterval(
235 | () => {
236 | this.setState({
237 | currentTime: (new Date()).getTime()
238 | })
239 | countingTime = this.state.timeAccumulation + this.state.currentTime - this.state.initialTime;
240 | minute = Math.floor(countingTime/(60*1000));
241 | second = Math.floor((countingTime-6000*minute)/1000);
242 | milSecond = Math.floor((countingTime%1000)/10);
243 | seccountingTime = countingTime - this.state.recordTime;
244 | secminute = Math.floor(seccountingTime/(60*1000));
245 | secsecond = Math.floor((seccountingTime-6000*secminute)/1000);
246 | secmilSecond = Math.floor((seccountingTime%1000)/10);
247 | this.setState({
248 | totalTime: (minute<10? "0"+minute:minute)+":"+(second<10? "0"+second:second)+"."+(milSecond<10? "0"+milSecond:milSecond),
249 | sectionTime: (secminute<10? "0"+secminute:secminute)+":"+(secsecond<10? "0"+secsecond:secsecond)+"."+(secmilSecond<10? "0"+secmilSecond:secmilSecond),
250 | })
251 | if (this.state.stopWatch) {
252 | this.setState({
253 | timeAccumulation: countingTime
254 | })
255 | clearInterval(interval)
256 | };
257 | }, 50);
258 | }
259 |
260 | stopWatch() {
261 | this.setState({
262 | stopWatch: true
263 | })
264 | }
265 |
266 | addRecord() {
267 | let {recordCounter, record} = this.state;
268 | recordCounter++;
269 | if (recordCounter<8) {
270 | record.pop();
271 | }
272 | record.unshift({
273 | title: "计次" + recordCounter,
274 | time: this.state.sectionTime
275 | });
276 | this.setState({
277 | recordTime: this.state.timeAccumulation + this.state.currentTime - this.state.initialTime,
278 | recordCounter: recordCounter,
279 | record: record
280 | })
281 | }
282 |
283 | clearRecord() {
284 | this.setState({
285 | stopWatch: false,
286 | resetWatch: true,
287 | intialTime: 0,
288 | currentTime:0,
289 | recordTime:0,
290 | timeAccumulation:0,
291 | totalTime: "00:00.00",
292 | sectionTime: "00:00.00",
293 | recordCounter: 0,
294 | record:[
295 | {title:"",time:""},
296 | {title:"",time:""},
297 | {title:"",time:""},
298 | {title:"",time:""},
299 | {title:"",time:""},
300 | {title:"",time:""},
301 | {title:"",time:""}
302 | ],
303 | });
304 | }
305 |
306 | render() {
307 | return (
308 |
313 |
316 | this.addRecord()}
318 | clearRecord={() => this.clearRecord()}
319 | startWatch={() => this.startWatch()}
320 | stopWatch={() => this.stopWatch()} />
321 |
322 |
323 | )
324 | }
325 | }
--------------------------------------------------------------------------------