編輯:關於Android編程
由於官方的Android原生UI組件解釋的並不是很完整,根據個人的不斷摸索,終於成功完成原生組件的制作,所以寫下這篇文章作為記錄,也給讓小白們少走些彎路。
我這裡通過講解制作一個繪圓組件的流程,來學習制作android原生UI組件。這個繪圓組件並沒有實際的使用價值,只是為了更容易的了解android原生UI組件的制作過程。好了廢話不多說,現在開始吧。
react-native版本:0.33.0首先初始化react-native項目,最好能弄個VPN
react-native init AndroidNativeModule
初次build android項目,先打開虛擬機或連接手機。
react-native run-android
項目的創建就講到這,詳細的項目創建和排錯請自行百度。現在我們用Android Stuido進入android項目。
創建基本的UI組件框架,這裡組件名稱嚴格更具功能進行命名,為了看的更清楚進行了一些打包
接下來給創建好的java添加基本結構,然後在後面更具需要添加細節功能
CircleView.java 基礎結構package com.androidnativemodule.module.circle; import android.content.Context; import android.view.View; /** * 圓形組件組件基礎類 */ public class CircleView extends View { public CircleView(Context context) { super(context); } }
UI組件繼承於View類,這裡沒有加什麼功能,就創建一個基本的類
CircleManager.javapackage com.androidnativemodule.module.circle; import com.facebook.react.uimanager.SimpleViewManager; import com.facebook.react.uimanager.ThemedReactContext; /** * 圓形組件基礎類管理器 */ public class CircleManager extends SimpleViewManager{ /** * 設置js引用名 * @return String */ @Override public String getName() { return "MCircle"; } /** * 創建UI組件實例 * @param reactContext * @return CircleView */ @Override protected CircleView createViewInstance(ThemedReactContext reactContext) { return new CircleView(reactContext); } }
所有的組件管理器需要繼承SimpleViewManager類,後面加上自己定義的組件基礎類,下面2個方法是SimpleViewManager類的必須實現的方法,記住getName()返回的名字要和JS裡的應用名進行統一。
MainPackge.javapackage com.androidnativemodule; import com.androidnativemodule.module.circle.CircleManager; import com.facebook.react.ReactPackage; import com.facebook.react.bridge.JavaScriptModule; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.uimanager.ViewManager; import java.util.Arrays; import java.util.Collections; import java.util.List; /** * 自定義組件模塊注冊類 */ public class MainPackage implements ReactPackage { /** * 創建原生模塊 * @param reactContext * @return */ @Override public ListcreateNativeModules(ReactApplicationContext reactContext) { return Collections.emptyList(); } @Override public List > createJSModules() { return Collections.emptyList(); } /** * 創建原生UI組件控制器 * @param reactContext * @return */ @Override public List createViewManagers(ReactApplicationContext reactContext) { return Arrays. asList( new CircleManager() ); } }
這個是注冊類,實現ReactPackage接口,可以想自己設計的組件統一寫在這個類中,然後一起在Application中注冊,注意:返回空值需要返回Collections.emptyList()。它還可以注冊原生模塊,這個官方有詳細的講解,地址如下:http://facebook.github.io/react-native/docs/native-modules-android.html
注冊類寫好後,還需要將這個類加載進Application中,我們在通過MainApplication中將其加入進去。
MainApplication.java
package com.androidnativemodule;
import android.app.Application;
import android.util.Log;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import java.util.Arrays;
import java.util.List;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
protected boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List getPackages() {
return Arrays.asList(
new MainReactPackage(),
new MainPackage() // 在這裡加載我們自己的注冊類
);
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
}
到這裡我們的自定義UI組件框架基本完成,我們可以run一下看看,如果沒有效果,可以嘗試重新
react-native run-android 下。
在Android Monitor中可以看到已經加載了我們的CircleModule,只有有沒我們JS並沒有實例話他,所以
Could not find generated setter for class com.androidnativemodule.module.circle.CircleManager。
<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxjb2RlPjxjb2RlPjxjb2RlPkNpcmNsZVZpZXcuamF2YSA8L2NvZGU+PC9jb2RlPjwvY29kZT4NCjxwcmUgY2xhc3M9"brush:java;">
接下來我們給我們的原生UI組件加上功能。
package com.androidnativemodule.module.circle;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.Log;
import android.view.View;
/**
* 圓形組件組件基礎類
*/
public class CircleView extends View {
protected String TAG = "CircleView";
private Paint mPaint; // 畫筆
public CircleView(Context context) {
super(context);
mPaint = new Paint();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(100, 100, 100, mPaint); // 畫一個半徑為100px的圓
Log.d(TAG, "繪圖");
}
}
這裡我先在CircleView內寫死代碼,看看這個原生UI到底能不能在JS中使用
現在我們來到react-native項目,我們先定制一個Circle組件的JS接口,方便其他組件調用。
創建Circle.js
import { PropTypes } from 'react';
import { requireNativeComponent, View } from 'react-native';
const MCircle = requireNativeComponent('MCircle', {
propTypes: {
...View.propTypes // 包含默認的View的屬性
},
});
export default MCircle;
使用requireNativeComponent根據先前在管理器中定義好的組件名引用原生組件,由於我們還沒創建接口,所以這個組件暫時只有父類View的接口。
現在我們在index.android.js中實例化組件看看效果
index.android.js
'use strict';
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
import Circle from './Circle';
class AndroidNativeModule extends Component {
render() {
return (
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
}
});
AppRegistry.registerComponent('AndroidNativeModule', () => AndroidNativeModule);
效果圖:
可以看到成功使用Android canvas 畫了一個圓
現在我們給他加一些接口,從而實現JS和JAVA的通訊,直接在JS中更改組件樣式。
CircleView.java
package com.androidnativemodule.module.circle;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.Log;
import android.view.View;
import com.facebook.react.uimanager.PixelUtil;
/**
* 圓形組件組件基礎類
*/
public class CircleView extends View {
protected String TAG = "CircleView";
private Paint mPaint; // 畫筆
private float mRadius; // 圓的半徑
public CircleView(Context context) {
super(context);
mPaint = new Paint();
}
/**
* 設置圓的背景色
* @param color
*/
public void setColor(Integer color) {
mPaint.setColor(color); // 設置畫筆顏色
invalidate(); // 更新畫板
}
/**
* 設置圓的半徑
* @param radius
*/
public void setRadius(Integer radius) {
/**
* 由於JS傳過的數字是dip單位,需要轉換為實際像素
* 使用com.facebook.react.uimanager包中的PixelUtil,進行轉換
*/
mRadius = PixelUtil.toPixelFromDIP(radius);
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(100, 100, 100, mPaint); // 畫一個半徑為100px的圓
Log.d(TAG, "繪圖");
}
}
這裡添加了2個接口,實現對圓的大小和顏色更改,還使用了
PixelUtil實現像素的轉換
CircleManager.java
package com.androidnativemodule.module.circle;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.annotations.ReactProp;
/**
* 圓形組件基礎類管理器
*/
public class CircleManager extends SimpleViewManager {
/**
* 設置js引用名
* @return String
*/
@Override
public String getName() {
return "MCircle";
}
/**
* 創建UI組件實例
* @param reactContext
* @return CircleView
*/
@Override
protected CircleView createViewInstance(ThemedReactContext reactContext) {
return new CircleView(reactContext);
}
/**
* 傳輸背景色參數
* @param view
* @param color
*/
@ReactProp(name = "color")
public void setColor(CircleView view, Integer color) {
view.setColor(color);
}
/**
* 傳輸半徑參數
* @param view
* @param radius
*/
@ReactProp(name = "radius")
public void setRadius(CircleView view, Integer radius) {
view.setRadius(radius);
}
}
管理器中引用接口,將參數傳輸過去
現在我們的CircleModule已經完成了,然後我們修改下Circle組件JS接口,實現接口使用。
Circle.js
'use strict';
import React, { Component, PropTypes } from 'react';
import {
View,
requireNativeComponent,
processColor // 字符Color轉換為數字
} from 'react-native';
const MCircle = requireNativeComponent('MCircle', {
propTypes: {
color: PropTypes.number,
radius: PropTypes.number,
...View.propTypes // 包含默認的View的屬性
},
});
class Circle extends Component {
static propTypes = {
radius: PropTypes.number,
color: PropTypes.string, // 這裡傳過來的是string
...View.propTypes // 包含默認的View的屬性
}
render() {
const { style, radius, color } = this.props;
return (
);
}
}
module.exports = Circle;
由於color使用的是String,我們可以用react-native的processColor將其轉換為數字,從而可以讓java識別出顏色,為了方便使用,所以我這邊重寫創建了Component,作為中間組件,對color進行轉換。
然後我的就可以通過Circle.js使用CircleModule了,例如:
效果圖:
到此Android自定義原生UI組件CircleModule的設計就結束了,如果有錯誤的地方,大家可以指出來反饋給我,也希望大家可以將自己的react-native開發心得分享出來,大家一起來學習。
本文代碼以MTK平台Android 4.4為分析對象,與Google原生AOSP有些許差異,請讀者知悉。 本文主要介紹MTK Android開機時,SIM卡的Fram
直接上圖: 在android 中導入項目後 包出現錯誤的解決方法 選中項目,右擊打開Proper
項目地址:XBanner簡介:功能強大的圖片無限自動輪播控件,可支持自定義狀態點及指示器顯示位置等功能支持圖片無限輪播的控件,可進行自定義功能。主要功能:支持根據服務端返
側滑菜單的實現方式:SlidingMenu開源庫:https://github.com/jfeinstein10/SlidingMenuDrawerLayout:是201