天天看點

flutter 自己定義多選

自定義多選:

2022-06-19 22:48:57 星期日

新學的flutter 對各種的文法和代碼技巧不是很熟練。沒有考慮那麼多的自定義話編輯,隻是簡單的進行的了一個多選組建的封裝,符合目前的我需要的邏輯。

僅供新手參考。希望大家多多指導

預覽

flutter 自己定義多選

實作 多選中的 每一項的代碼:

點選檢視代碼

import 'dart:core';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter/material.dart';

/// @author XCC
/// @建立時間:2022/5/9
/// 工具菜單checkbox版子項
class ToolMenuCheckboxItemWidget extends StatelessWidget {
  /// 顯示的title
  final String title;
  final int value;

  /// 點選回調
  final Function click;
  final double? width;
  final double? height;
  final bool isActive;
  final Color? backgroundColor; // 未選中背景色

  final Color? activeBackgroundColor; // 選中的的顔色 沒傳取主題色
  final BoxBorder? activeBorder; // 選中的border

  final BorderRadiusGeometry? borderRadius; // 圓角
  final TextStyle? textStyle; // 文字樣式
  final TextStyle? activeTextStyle; //  選中的文字樣式

  const ToolMenuCheckboxItemWidget(
      {Key? key,
      this.isActive = false,
      required this.title,
      required this.click,
      required this.value,
      this.width,
      this.height,
      this.activeBackgroundColor,
      this.backgroundColor,
      this.activeBorder,
      this.borderRadius,
      this.textStyle,
      this.activeTextStyle})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    TextStyle defaultTextStyle = const TextStyle();

    double defaultWidth = width ?? 100.w;
    double defaultHeight = height ?? 50.w;
    return Container(
      // 點選右波紋效果
      width: defaultWidth,
      height: defaultHeight,
      clipBehavior: Clip.hardEdge,
      decoration: BoxDecoration(
        border: !isActive
            ? Border.all(width: 1.w, color: Colors.transparent)
            : activeBorder,
        borderRadius: borderRadius ?? BorderRadius.circular(defaultHeight / 2),
      ),
      child: Material(
        color: isActive
            ? activeBackgroundColor ?? Theme.of(context).primaryColor
            : backgroundColor ?? Colors.white60,
        borderRadius: borderRadius ?? BorderRadius.circular(defaultHeight / 2),
        child: Ink(
          child: InkWell(
            onTap: () {
              click(value);
            },
            child: Center(
              child: Text(title,
                  style: isActive
                      ? activeTextStyle ?? defaultTextStyle
                      : textStyle ?? defaultTextStyle),
            ),
          ),
        ),
      ),
    );
  }
}

           

實作多選元件的代碼:

點選檢視代碼

import 'dart:core';
import 'package:communityApp/home_system/components/check_box_widget/tool_menu_check_box_item_widget.dart';
import 'package:communityApp/home_system/models/recommendToday.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter/material.dart';

/// @author XCC
/// @建立時間:2022/5/9
/// 工具菜單checkbox版
class ToolMenuCheckBoxWidget extends StatefulWidget {
  final List<FindSimilarYouWant> children;
  final Function click; // 點選回調 傳回第n個的選中情況
  final double? width; //item 寬
  final double? height; // item 高
  final List? selectList; // 選中的資料

  final Color? backgroundColor; // 背景色
  final Color? activeBackgroundColor; // 選中的背景顔色
  final BoxBorder? activeBorder; // 選中的邊框
  final BorderRadiusGeometry? borderRadius; // 圓角
  final TextStyle? textStyle; // 文字樣式
  final TextStyle? activeTextStyle; //  選中的文字樣式
  const ToolMenuCheckBoxWidget(
      {Key? key,
      required this.children,
      required this.click,
      this.width,
      this.height,
      this.activeBackgroundColor,
      this.activeBorder,
      this.selectList,
      this.backgroundColor,
      this.borderRadius,
      this.textStyle,
      this.activeTextStyle})
      : super(key: key);

  @override
  State<ToolMenuCheckBoxWidget> createState() => _ToolMenuCheckBoxWidgetState();
}

class _ToolMenuCheckBoxWidgetState extends State<ToolMenuCheckBoxWidget> {
  late List<FindSimilarYouWant> items;
  late final List _selctedList = widget.selectList ?? [];

  @override
  void initState() {
    // 初始化目前選中
    items = widget.children;
    super.initState();
  }

// 是否選中
  bool eachItems(val) {
    bool falg = false;
    for (var ele in _selctedList) {
      if (ele == val) {
        falg = true;
      }
    }
    return falg;
  }

  @override
  Widget build(BuildContext context) {
    return Wrap(
      spacing: 10.w,
      runSpacing: 10.w,
      alignment: WrapAlignment.start,
      children: widget.children.map((val) {
        return ToolMenuCheckboxItemWidget(
          title: val.title,
          value: val.value,
          click: (int selectValue) {
            // bool galg = false;
            // setState(() {
            //   _selctedList.removeWhere((element) {
            //     galg = true;
            //     return element == selectValue;
            //   });
            //   if (!galg) {
            //     setState(() {
            //       _selctedList.add(val.value);
            //     });
            //   }
            // });

            if (_selctedList.contains(selectValue)) {
              setState(() {
                _selctedList.remove(selectValue);
              });
            } else {
              setState(() {
                _selctedList.add(selectValue);
              });
            }
            widget.click(_selctedList);
          },
          width: widget.width,
          height: widget.height,
          isActive: eachItems(val.value),
          backgroundColor: widget.backgroundColor,
          textStyle: widget.textStyle,
          activeTextStyle: widget.activeTextStyle,
          activeBackgroundColor: widget.activeBackgroundColor,
          activeBorder: widget.activeBorder,
          borderRadius: widget.borderRadius,
        );
      }).toList(),
    );
  }
}

           

試用的代碼:

點選檢視代碼

///初始化代碼
widget.selectlist = [];
var data = [
  {"title": 'aaa', "value": 1},
  {"title": 'bbb', "value": 2},
  {"title": 'ccc', "value": 3},
  {"title": 'ddd', "value": 4},
];
youList = data.map((e) => FindSimilarYouWant.froJson(e)).toList();



//// builder 的代碼
ToolMenuCheckBoxWidget(
  width: 105.w,
  height: 36.w,
  children: youList,  ///資料清單
  selectList: widget.selectlist,  ///預設選中的代碼
  backgroundColor: const Color(0xFFF3F9FB),
  activeBackgroundColor: Colors.white,
  activeBorder:
      Border.all(width: 1.w, color: const Color(0xFFFF8A00)),
  activeTextStyle: TextStyle(
    color: const Color(0xFFFF8A00),
    fontSize: 14.sp,
    fontWeight: FontWeight.w500,
  ),
  textStyle: TextStyle(fontSize: 14.sp),
  click: (List selection) {
    setState(() {
      widget.selectlist = selection;    ///接受選中的資料
    });
    print('======>$selection');
  },
)
           

EndTip:

在傳遞  children 這個Map 清單,進行map周遊去拿到Map裡資料的時候 , 會出現資料格式報錯的問題 (超級惡心的問題!!!!),我寫了一個models來對傳遞的children資料 進行類型聲明。

點選檢視代碼

class FindSimilarYouWant {
  late String title;
  late int value;
  FindSimilarYouWant({required this.title, required this.value});

  FindSimilarYouWant.froJson(Map<String, dynamic> json) {
    title = json['title'];
    value = json['value'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['title'] = title;
    data['value'] = value;
    return data;
  }
}

           

###