首页 > 解决方案 > 将android原生小部件添加到flutter(宽度道具方法和监听器)

问题描述

我想在我的颤振项目中使用这个本机小部件(仅限 android 端)。

https://github.com/mmin18/RealtimeBlurView

(我知道有实时模糊的替代方案,但这只是其他一些小部件之间的一个例子,我正在寻找一个通用的解决方案和一个示例代码)。所以:

谢谢你的帮助。

标签: androidflutterdart

解决方案


如果你想在 Flutter 中使用 android 特定库或 iOS 特定库,你应该使用MethodChannel

所以对于您的问题,我的解决方案是在您的 android 框架中添加RealtimeBlurView依赖项,然后使用MethodChannel访问它

所以让我们开始吧:

  1. 创建名为BlurViewWidget的小部件,如下所示:
import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

typedef BlurViewWidgetCreatedCallback = void Function(
    BlurViewWidgetController controller);

class BlurViewWidget extends StatefulWidget {
  const BlurViewWidget({
    Key key,
    this.onBlurViewWidgetCreated,
  }) : super(key: key);

  final BlurViewWidgetCreatedCallback onBlurViewWidgetCreated;

  @override
  State<StatefulWidget> createState() => _BlurViewWidgetState();
}

class _BlurViewWidgetState extends State<BlurViewWidget> {
  @override
  Widget build(BuildContext context) {
    if (defaultTargetPlatform == TargetPlatform.android) {
      return AndroidView(
        viewType: 'plugins/blur_view_widget',
        onPlatformViewCreated: _onPlatformViewCreated,
      );
    }
    return const Text('iOS platform version is not implemented yet.');
  }

  void _onPlatformViewCreated(int id) {
    if (widget.onBlurViewWidgetCreated == null) {
      return;
    }
    widget.onBlurViewWidgetCreated(BlurViewWidgetController._(id));
  }
}

class BlurViewWidgetController {
  BlurViewWidgetController._(int id)
      : _channel = MethodChannel('plugins/blur_view_widget_$id');

  final MethodChannel _channel;

  Future<void> draggable(bool value) async {
    return _channel.invokeMethod('draggable',value);
  }
}

2.打开android文件夹并添加RealtimeBlurView依赖项,如下所示:

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'com.github.mmin18:realtimeblurview:1.2.1'
}

3.在 res 文件夹中创建 layout forlder 并在其中创建blur_view_widget.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <RelativeLayout
        android:id="@+id/blur_frame"
        android:gravity="center"
        android:background="@android:color/darker_gray"
        android:layout_width="360dp"
        android:layout_height="360dp"
        android:layout_gravity="center">

        <com.github.mmin18.widget.RealtimeBlurView
            android:id="@+id/blur_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </RelativeLayout>

</FrameLayout>

4.转到src/your/package/name并创建BlurViewWidget.kt,该类负责为您的 xml 视图和MethodChannel响应:

package com.taleb.flutter_platformview

import android.annotation.SuppressLint
import android.content.Context
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import io.flutter.plugin.common.BinaryMessenger
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.platform.PlatformView

class BlurViewWidget internal constructor(context: Context, id: Int, messenger: BinaryMessenger) : PlatformView, MethodCallHandler {
    private var view: View = LayoutInflater.from(context).inflate(R.layout.blur_view_widget, null)
    private val methodChannel: MethodChannel = MethodChannel(messenger, "plugins/blur_view_widget_$id")

    override fun getView(): View {
        return view
    }

    init {
        methodChannel.setMethodCallHandler(this)
    }

    override fun onMethodCall(methodCall: MethodCall, result: MethodChannel.Result) {
        when (methodCall.method) {
            "draggable" -> draggable(methodCall, result)
            else -> result.notImplemented()
        }
    }


    @SuppressLint("ClickableViewAccessibility")
    private fun draggable(methodCall: MethodCall, result: Result) {
        val isDraggable: Boolean = methodCall.arguments as Boolean
        if (isDraggable)
            view.findViewById<View>(R.id.blur_frame).setOnTouchListener(touchListener)
        else
            view.findViewById<View>(R.id.blur_frame).setOnTouchListener(null)

        result.success(null)
    }

    override fun dispose() {
    }

    private val touchListener: View.OnTouchListener = object : View.OnTouchListener {
        var dx = 0f
        var dy = 0f
        override fun onTouch(v: View?, event: MotionEvent): Boolean {
            val view = view.findViewById<View>(R.id.blur_frame)
            if (event.action == MotionEvent.ACTION_DOWN) {
                dx = view.x - event.rawX
                dy = view.y - event.rawY
            } else if (event.action == MotionEvent.ACTION_MOVE) {
                view.x = event.rawX + dx
                view.y = event.rawY + dy
            }
            return true
        }
    }


}

5.然后创建BlurViewWidgetFactory.kt

package com.taleb.flutter_platformview

import android.content.Context
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.StandardMessageCodec
import io.flutter.plugin.platform.PlatformView
import io.flutter.plugin.platform.PlatformViewFactory

class BlurViewWidgetFactory(private val messenger: BinaryMessenger) : PlatformViewFactory(StandardMessageCodec.INSTANCE) {

    override fun create(context: Context, id: Int, o: Any?): PlatformView {
        return BlurViewWidget(context = context, id = id, messenger = messenger)
    }
}

6.然后创建BlurViewWidgetPlugin.kt

package com.taleb.flutter_platformview
import io.flutter.plugin.common.PluginRegistry.Registrar

object BlurViewWidgetPlugin {
    fun registerWith(registrar: Registrar) {
        registrar
                .platformViewRegistry()
                .registerViewFactory(
                        "plugins/blur_view_widget", BlurViewWidgetFactory(registrar.messenger()))
    }
}

7.并更改MainActivity.kt如下所示:

package com.taleb.flutter_platformview

import android.os.Bundle
import io.flutter.app.FlutterActivity
import io.flutter.plugins.GeneratedPluginRegistrant

class MainActivity: FlutterActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        BlurViewWidgetPlugin.registerWith(this.registrarFor("com.taleb.flutter_platformview.BlurViewWidgetPlugin"))
    }
}

最后从main.dart测试你的小部件,如下所示:

import 'package:flutter/material.dart';
import 'package:flutter_platformview/widget/blur_view_widget.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.blueAccent,
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: BlurViewWidget(
          onBlurViewWidgetCreated: _onBlurViewWidgetCreated,
        ),
      ),
    );
  }

  void _onBlurViewWidgetCreated(BlurViewWidgetController controller){
    controller.draggable(true);
  }
}

就是这样。你可以在这里得到这个答案的完整源代码


推荐阅读