Я пытаюсь создать виджет из карты навигации собственного вида, используя методы каналов и AndroidViews, но продолжаю сталкиваться с этой проблемой:
E/MethodChannel#flutter/platform_views( 2258): Failed to handle method call
E/MethodChannel#flutter/platform_views( 2258): java.lang.IllegalArgumentException: Cannot add a null child view to a ViewGroup.
Вот код флаттера:
Main.dart
import 'navigation_view.dart';
import 'package:expandable_bottom_sheet/expandable_bottom_sheet.dart';
import 'package:flutter/material.dart';
import 'customButton1.dart';
import 'Constantes.dart';
void main() => runApp(MaterialApp(home: TextViewExample()));
class TextViewExample extends StatefulWidget {
@override
_TextViewExampleState createState() => _TextViewExampleState();
}
class _TextViewExampleState extends State<TextViewExample>
with SingleTickerProviderStateMixin {
@override
void initState() {
super.initState();
}
Widget build(BuildContext context) {
// var s = NavigationView(
// onNavigationViewCreated: _onNavigationViewCreated,
// );
double screenWidth, screenHeight;
Size size = MediaQuery.of(context).size;
screenHeight = size.height;
screenWidth = size.width;
print("FLUTTER INIT");
return Scaffold(
body: SafeArea(
child: Stack(children: [
Positioned(
width: screenWidth,
height: screenHeight - 220,
child: Container(
child: NavigationView(
onNavigationViewCreated: _onNavigationViewCreated,
),
),
),
Positioned(
bottom: 75,
child: Container(
height: screenHeight,
width: screenWidth,
void _onNavigationViewCreated(NavigationViewController controller) {}
}
Вот навигационный_двиг_dart
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
typedef void NavigationViewCreatedCallback(NavigationViewController controller);
class NavigationView extends StatefulWidget {
const NavigationView({
Key key,
this.onNavigationViewCreated,
}) : super(key: key);
final NavigationViewCreatedCallback onNavigationViewCreated;
@override
State<StatefulWidget> createState() => _NavigationViewState();
}
class _NavigationViewState extends State<NavigationView> {
@override
Widget build(BuildContext context) {
if (defaultTargetPlatform == TargetPlatform.android) {
return AndroidView(
viewType: 'com.Mavic.Cabinn/navigationview',
onPlatformViewCreated: _onPlatformViewCreated,
);
}
return Text(
'$defaultTargetPlatform is not yet supported by the navigation_view plugin');
}
void _onPlatformViewCreated(int id) {
if (widget.onNavigationViewCreated == null) {
return;
}
widget.onNavigationViewCreated(new NavigationViewController._(id));
}
}
class NavigationViewController {
NavigationViewController._(int id)
: _channel = new MethodChannel(
'com.Mavic.Cabinn/navigationview$id');
final MethodChannel _channel;
// Future<void> setNavigation() async {
// try {
// Future.delayed(const Duration(seconds: 1), () async {
// await _channel.invokeMethod('EmpezarNavegacion');
//
// return;
// });
// } on PlatformException catch (e) {
// print(e);
// }
// Future<void> setNavigation() async {
// assert(AndroidView != null);
// return _channel.invokeMethod('EmpezarNavegacion');
// }
//}
Future<dynamic> setNavigation() async {
String message;
try {
final String result = await _channel.invokeMethod('EmpezarNagevacion');
message = result;
} on PlatformException catch (e) {
print(message);
}
}
}
И, наконец, Java Код
package com.example.embeded_java_test;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.location.Location;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.AbsoluteSizeSpan;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.mapbox.api.directions.v5.DirectionsCriteria;
import com.mapbox.api.directions.v5.models.BannerInstructions;
import com.mapbox.api.directions.v5.models.DirectionsResponse;
import com.mapbox.api.directions.v5.models.DirectionsRoute;
import com.mapbox.geojson.Point;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.services.android.navigation.ui.v5.route.NavigationMapRoute;
import com.example.embeded_java_test.R;
import com.mapbox.services.android.navigation.ui.v5.NavigationView;
import com.mapbox.services.android.navigation.ui.v5.NavigationViewOptions;
import com.mapbox.services.android.navigation.ui.v5.OnNavigationReadyCallback;
//import com.mapbox.services.android.navigation.ui.v5.listeners.BannerInstructionsListener;
//import com.mapbox.services.android.navigation.ui.v5.listeners.InstructionListListener;
import com.mapbox.services.android.navigation.ui.v5.listeners.BannerInstructionsListener;
import com.mapbox.services.android.navigation.ui.v5.listeners.InstructionListListener;
import com.mapbox.services.android.navigation.ui.v5.listeners.NavigationListener;
//import com.mapbox.services.android.navigation.ui.v5.listeners.SpeechAnnouncementListener;
//import com.mapbox.services.android.navigation.ui.v5.voice.SpeechAnnouncement;
import com.mapbox.services.android.navigation.ui.v5.listeners.SpeechAnnouncementListener;
import com.mapbox.services.android.navigation.ui.v5.voice.SpeechAnnouncement;
import com.mapbox.services.android.navigation.v5.navigation.NavigationRoute;
import com.mapbox.services.android.navigation.v5.routeprogress.ProgressChangeListener;
import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgress;
import java.util.Locale;
import java.util.concurrent.Future;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import org.jetbrains.annotations.NotNull;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.platform.PlatformView;
import com.example.embeded_java_test.MainActivity;
public class EmbeddedNavigationActivity extends AppCompatActivity implements OnNavigationReadyCallback,
NavigationListener, ProgressChangeListener, InstructionListListener, SpeechAnnouncementListener,
BannerInstructionsListener,PlatformView, MethodCallHandler {
private Point ORIGIN = Point.fromLngLat(-77.03194990754128, 38.909664963450105);
private Point DESTINATION = Point.fromLngLat(-77.0270025730133, 38.91057077063121);
private final int INITIAL_ZOOM = 16;
private NavigationView navigationView;
private View spacer;
private TextView speedWidget;
private final MethodChannel methodChannel;
private boolean bottomSheetVisible = true;
private boolean instructionListShown = false;
private NavigationMapRoute navigationMapRoute;
// @Override
// public void onCreate(@Nullable Bundle savedInstanceState) {
// super.onCreate(savedInstanceState);
// navigationView = findViewById(R.id.navigationView);
// navigationView.onCreate(savedInstanceState);
// setTheme(R.style.Theme_AppCompat_Light_NoActionBar);
// //initNightMode();
@Override
public void dispose() {}
private Context context;
private Activity activity;
private Bundle savedInstance;
public EmbeddedNavigationActivity(Context currentContext, Activity currentActivity, Bundle currentBundle,BinaryMessenger messenger, int id)
{
new MainActivity();
MainActivity newMain = new MainActivity();
this.activity=this;
System.out.println(activity + "Activity");
this.context=this;
System.out.println(context + "Context");
System.out.println(activity);
Log.i("Here", "Constructor!!!");
System.out.println(activity + " This Activity");
this.savedInstance=currentBundle;
System.out.println(currentContext + "Context");
//
methodChannel = new MethodChannel(messenger, "com.Mavic.Cabinn/navigationview_" + id);
methodChannel.setMethodCallHandler(this);
}
@Override
public View getView() {
Log.i("Here", "GETVIEW");
return navigationView;
}
public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
Log.i("MSG", "CALLING SET TEXT");
switch (methodCall.method) {
case "EmpezarNavegacion":
EmpezarNavegacion(methodCall, result);
result.success(null);
break;
default:
result.notImplemented();
}
}
public void EmpezarNavegacion(MethodCall methodCall, Result result)
{
double LtLang = (double) methodCall.arguments;
result.success(null);
Mapbox.getInstance(context, activity.getString(R.string.access_token));
activity.setContentView(R.layout.cabinn_nav);
navigationView =activity.findViewById(R.id.navigationView);
//super.onCreate(savedInstanceState);
//Mapbox.getInstance(this,getString(R.string.access_token));
//navigationView =(NavigationView)findViewById(R.id.navigationView);
if(navigationView==null)
{
Log.e("ERROR NAVEGACION","NAVIGATION VIEW ES NULL, NO ESTA SETEADO EL CONTENT");
return;
}
//fabNightModeToggle = findViewById(R.id.fabToggleNightMode);
//speedWidget = findViewById(R.id.speed_limit);
//spacer = findViewById(R.id.spacer);
//setSpeedWidgetAnchor(R.id.summaryBottomSheet);
// ORIGIN=ORIGEN;
// DESTINATION=DESTINO;
CameraPosition initialPosition = new CameraPosition.Builder()
.target(new LatLng(ORIGIN.latitude(), ORIGIN.longitude()))
.zoom(INITIAL_ZOOM)
.build();
//navigationView.onCreate(savedInstanceState);
navigationView.onCreate(this.savedInstance);
navigationView.initialize(this, initialPosition);
}
@Override
public void onNavigationReady(boolean isRunning) {
//navigationView.findViewById(R.id.instructionLayoutText).setVisibility(View.INVISIBLE);
navigationView.findViewById(R.id.instructionListLayout).setVisibility(View.INVISIBLE);
//navigationView.findViewById(R.id.maneuverView).setVisibility(View.INVISIBLE);
navigationView.findViewById(R.id.summaryBottomSheet).setVisibility(View.INVISIBLE);
navigationView.findViewById(R.id.feedbackFab).setVisibility(View.INVISIBLE);
navigationView.findViewById(R.id.subStepText).setVisibility(View.INVISIBLE);
navigationView.findViewById(R.id.subStepLayout).setVisibility(View.INVISIBLE);
navigationView.findViewById(R.id.summaryContentLayout).setVisibility(View.INVISIBLE);
//navigationView.findViewById(R.id.subManeuverView).setVisibility(View.INVISIBLE);
//navigationView.findViewById(R.id.stepDistanceText).setVisibility(View.INVISIBLE);
//navigationView.findViewById(R.id.stepPrimaryText).setVisibility(View.INVISIBLE);
//navigationView.findViewById(R.id.stepSecondaryText).setVisibility(View.INVISIBLE);
fetchRoute();
}
public void onStart_() {
Log.i("NAV","NAVIGATION START");
navigationView.onStart();
}
public void onResume_() {
navigationView.onResume();
}
public void onLowMemory_() {
navigationView.onLowMemory();
}
public void onBackPressed_() {
// If the navigation view didn't need to do anything, call super
if (!navigationView.onBackPressed()) {
super.onBackPressed();
}
}
protected void onSaveInstanceState_(Bundle outState) {
navigationView.onSaveInstanceState(outState);
}
protected void onRestoreInstanceState_(Bundle savedInstanceState) {
navigationView.onRestoreInstanceState(savedInstanceState);
}
public void onPause_() {
navigationView.onPause();
}
public void onStop_() {
navigationView.onStop();
}
protected void onDestroy_() {
navigationView.onDestroy();
if (isFinishing()) {
saveNightModeToPreferences(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY);
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY);
}
}
@Override
public void onCancelNavigation() {
// Navigation canceled, finish the activity
finish();
}
@Override
public void onNavigationFinished() {
// Intentionally empty
}
@Override
public void onNavigationRunning() {
// Intentionally empty
}
@Override
public void onProgressChange(Location location, RouteProgress routeProgress) {
setSpeed(location);
}
@Override
public void onInstructionListVisibilityChanged(boolean shown) {
instructionListShown = shown;
speedWidget.setVisibility(shown ? View.GONE : View.VISIBLE);
if (instructionListShown) {
// fabNightModeToggle.hide();
} else if (bottomSheetVisible) {
//fabNightModeToggle.show();
}
}
@Override
public SpeechAnnouncement willVoice(SpeechAnnouncement announcement) {
return SpeechAnnouncement.builder().announcement("All announcements will be the same.").build();
}
@Override
public BannerInstructions willDisplay(BannerInstructions instructions) {
return instructions;
}
private void startNavigation(DirectionsRoute directionsRoute) {
NavigationViewOptions.Builder options =
NavigationViewOptions.builder()
.navigationListener(this)
.directionsRoute(directionsRoute)
.shouldSimulateRoute(true)
.progressChangeListener(this);
//.instructionListListener(this)
//.speechAnnouncementListener(this)
// .bannerInstructionsListener(this);
setBottomSheetCallback(options);
//setupNightModeFab();
navigationView.startNavigation(options.build());
}
private void fetchRoute() {
NavigationRoute.builder(this.context)
.accessToken(this.activity.getString(R.string.access_token))
.origin(ORIGIN)
.voiceUnits(DirectionsCriteria.METRIC)
.destination(DESTINATION)
.alternatives(true)
.build()
.getRoute(new Callback<DirectionsResponse>() {
@Override
public void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {
if(response.body() == null)
{
Log.e("ERROR RUTA","NO RUTA ENCONTRADA");
return;
}else if(response.body().routes().size()==0)
{
Log.e("ERROR RUTA","SIN RUTA ENCONTRADA");
return;
}
DirectionsRoute currentRoute = response.body().routes().get(0);
//navigationMapRoute.addRoute(currentRoute);
startNavigation(currentRoute);
}
@Override
public void onFailure(Call<DirectionsResponse> call, Throwable t) {
}
});
}
void simpleCallBack(Call<DirectionsResponse> call, Response<DirectionsResponse> response)
{
DirectionsRoute directionsRoute = response.body().routes().get(0);
startNavigation(directionsRoute);
}
private void setSpeedWidgetAnchor(@IdRes int res) {
//CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) spacer.getLayoutParams();
//layoutParams.setAnchorId(res);
//spacer.setLayoutParams(layoutParams);
}
private void setBottomSheetCallback(NavigationViewOptions.Builder options) {
options.bottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
switch (newState) {
case BottomSheetBehavior.STATE_HIDDEN:
bottomSheetVisible = false;
//fabNightModeToggle.hide();
setSpeedWidgetAnchor(R.id.recenterBtn);
break;
case BottomSheetBehavior.STATE_EXPANDED:
bottomSheetVisible = true;
break;
case BottomSheetBehavior.STATE_SETTLING:
if (!bottomSheetVisible) {
// View needs to be anchored to the bottom sheet before it is finished expanding
// because of the animation
//fabNightModeToggle.show();
setSpeedWidgetAnchor(R.id.summaryBottomSheet);
}
break;
default:
return;
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});
}
private void setupNightModeFab() {
//fabNightModeToggle.setOnClickListener(view -> toggleNightMode());
}
private void toggleNightMode() {
int currentNightMode = getCurrentNightMode();
alternateNightMode(currentNightMode);
}
private void initNightMode() {
// int nightMode = retrieveNightModeFromPreferences();
//AppCompatDelegate.setDefaultNightMode(nightMode);
}
private int getCurrentNightMode() {
return getResources().getConfiguration().uiMode
& Configuration.UI_MODE_NIGHT_MASK;
}
private void alternateNightMode(int currentNightMode) {
int newNightMode;
if (currentNightMode == Configuration.UI_MODE_NIGHT_YES) {
newNightMode = AppCompatDelegate.MODE_NIGHT_NO;
} else {
newNightMode = AppCompatDelegate.MODE_NIGHT_YES;
}
saveNightModeToPreferences(newNightMode);
recreate();
}
private void saveNightModeToPreferences(int nightMode) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = preferences.edit();
//editor.putInt(getString(R.string.current_night_mode), nightMode);
editor.apply();
}
private void setSpeed(Location location) {
String string = String.format("%d\nMPH", (int) (location.getSpeed() * 2.2369));
//int mphTextSize = getResources().getDimensionPixelSize(R.dimen.mph_text_size);
//int speedTextSize = getResources().getDimensionPixelSize(R.dimen.speed_text_size);
SpannableString spannableString = new SpannableString(string);
// spannableString.setSpan(new AbsoluteSizeSpan(mphTextSize),
// string.length() - 4, string.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
// spannableString.setSpan(new AbsoluteSizeSpan(speedTextSize),
// 0, string.length() - 3, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
}
}
Я использовал эту статью в качестве справочного материала, чтобы попытаться воспроизвести это, но я ударил многих ударов скорости, пытаясь заставить это работать должным образом: https://medium.com/flutter-community/flutter-platformview-how-to-create-flutter-widgets-from-native-views-366e378115b6
Это вывод моего доктора о трепетании:
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.12.13+hotfix.9, on Linux, locale en_US.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
[✓] Android Studio (version 3.6)
[✓] Connected device (1 available)
• No issues found!
Как я уже говорил, я пытался найти нулевое значение и искал высоко и низко вопросы, похожие на этот, но У меня не было такой удачи, потому что это не то, что я видел, сделал. Я также проверил, есть ли какие-либо плагины для создания и встроенной карты, и, к сожалению, на данный момент их нет.