شرح اضافة تاثير Parallax Effect على الصور في Flutter

شرح اضافة تاثير Parallax Effect على الصور في Flutter

شرح اضافة تاثير Parallax Effect على الصور في Flutter

في هذه المقالة سوف نشرح معكم واحد من اكثر التاثيرات جمالا في تطبيقات flutter ويعطي منظر رائببع لتطبيقك حيث يعمل على تاثير الصور وعمل تحريك لها اثناء عمل scroll كما هو موضح بالصورة الخاصه بالمقالة وكثير من المبرمجين يبحثون عن طريقة لاستخدام هذا التاثير في تطبيقاتهم ليعطي منظر جميل لهم ويمكنهم من تغيير الطريقة التقليديه لعرض التصميم الخاص بالصور في تطبيقاتهم والامر بسيط جدا جدا وسوفف نشرحه لكم في هذه المقالة .


إن حرفة تطوير تطبيقات الأجهزة المحمولة تتطلب عمالة مكثفة وتغير العالم الرقمي يوميًا. بناء البرمجيات للأجهزة المحمولة هو ما يستلزمه. تقنيات المعالجة الدقيقة المتقدمة مطلوبة لإنشاء تطبيقات الهاتف المحمول. وقد رفعت هذه التقنيات من مستوى إنشاء برامج الهاتف المحمول. على سبيل المثال ، يمكنك الآن تشغيل تطبيقات الأجهزة المحمولة على مجموعة متنوعة من الأنظمة الأساسية. بالإضافة إلى ذلك ، يتم إنشاء أفضل تطبيقات سطح المكتب للهواتف الذكية.


تطبيقات الأجهزة المحمولة التي تم إنشاؤها متاحة للتنزيل والتثبيت المسبق على أجهزة Android و iPhone. يمكن لكل من أجهزة Mac وأجهزة الكمبيوتر التي تعمل بنظام Windows الاستجابة لها. يستكشف المطورون الحقائق المتعلقة باستهلاك تطبيقات الأجهزة المحمولة لإنشاء تطبيقات الأجهزة المحمولة. يأخذون في الاعتبار مقدار الأموال التي ينفقها المستخدمون على هواتفهم الذكية وإمكانية تطوير تطبيقات الهاتف المحمول.


How to add Parallax Effect in Image Flutter

في هذه الصفحة سوف نعرض ال List view التي سوف تحتوي على الصور كما هو متعارف عليه وعرض التصميم والذي سوف نقوم بعمله في الجزء التالي والذي يعبر عن كل عنصر في هذه ال listView .


How to add Parallax Effect in Image Flutter

Parallax_Effect.dart


import 'dart:ui';
import 'package:flutter/material.dart';

class AllDestination extends StatefulWidget {
  final double padding;
  final double spacing;
  const AllDestination({Key? key,this.padding = 24, this.spacing = 24}) : super(key: key);

  @override
  State<AllDestination> createState() => _AllDestinationState();
}

class _AllDestinationState extends State<AllDestination> {
  static const imageW = 250.0;
  late final ScrollController _scrollController;
  late final double _indexFactor;
  double imageOffset = 0.0;

  @override
  void initState() {
    final deviceWidth = (window.physicalSize.shortestSide / window.devicePixelRatio);
    _indexFactor = (widget.spacing + imageW) / deviceWidth;
    imageOffset = -widget.padding / deviceWidth;

    _scrollController = ScrollController()
      ..addListener(() {
        setState(() {
          imageOffset = ((_scrollController.offset - widget.padding) / deviceWidth) ;
        });
      });

    super.initState();
  }

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
        height: 380,
        child: ListView.separated(
          physics: const BouncingScrollPhysics(),
          padding: EdgeInsets.symmetric(horizontal: widget.padding),
          controller: _scrollController,
          scrollDirection: Axis.horizontal,
          separatorBuilder: (_, __) => SizedBox(width: widget.spacing),
          itemCount: MockAllDestinations.data.length,
          itemBuilder: (_, index) => DestinationItem(
            index: index,
            details: MockAllDestinations.data[index],
            imageWidth: imageW,
            imageOffset: imageOffset,
            indexFactor: _indexFactor,
          ),
        ),
    );
  }
}


Design Item Parallax Effect

هذا الجزء يعبر عن كل عنصر في ال list السابقة والذي سوف نضيف التاثير لكل صورة من الصورة التي سوف نضعها كما هو موضح بالكود والصور الخاصه به في المقالة , الامر بسيط جدا يمكنك نسخ الكود التالي بشكل كامل والتعديل عليه في تطبيقك او استبدال الصور وبعض المحتويات فقط كل شيئ بين يديك .


Design Item Parallax Effect

DestinationItem.dart


import 'package:flutter/material.dart';
import 'dart:ui';

class DestinationItem extends StatelessWidget {
  final int index;
  final Destination details;
  final double imageWidth;
  final double imageOffset;
  final double indexFactor;

  const DestinationItem({
    Key? key,
    required this.index,
    required this.details,
    required this.imageWidth,
    required this.imageOffset,
    required this.indexFactor,
  }) : super(key: key);

  Widget image() {
    return Image.network(
      details.city,
      fit: BoxFit.cover,
      alignment: Alignment(-imageOffset + indexFactor * index, 0),
    );
  }

  Widget rating() {
    return Align(
      alignment: Alignment.topLeft,
      child: Padding(
        padding: const EdgeInsets.all(12),
        child: ClipRRect(
          borderRadius: BorderRadius.circular(32),
          child: BackdropFilter(
            filter: ImageFilter.blur(sigmaX: 8, sigmaY: 8),
            child: Container(
              height: 48,
              color: Colors.black.withOpacity(0.3),
              child: Padding(
                padding: const EdgeInsets.only(left: 12, right: 16),
                child: Row(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    const Icon(
                      Icons.star_rate_rounded,
                      color: Color(0xFFFFD600),
                      size: 20,
                    ),
                    const SizedBox(width: 8),
                    Padding(
                      padding: const EdgeInsets.only(top: 2),
                      child: Text(
                        details.rating,
                        style: const TextStyle(
                          color: Colors.white,
                          fontSize: 16,
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }

  Widget favoriteIcon() {
    return Align(
      alignment: Alignment.topRight,
      child: Padding(
        padding: const EdgeInsets.all(12),
        child: ClipRRect(
          borderRadius: BorderRadius.circular(32),
          child: BackdropFilter(
            filter: ImageFilter.blur(sigmaX: 8, sigmaY: 8),
            child: Container(
              width: 48,
              height: 48,
              color: Colors.black.withOpacity(0.3),
              child: const Icon(
                Icons.star,
                color: Colors.yellow,
              ),
            ),
          ),
        ),
      ),
    );
  }

  Widget bottomText() {

    return Align(
      alignment: Alignment.bottomCenter,
      child: Padding(
        padding: const EdgeInsets.all(12),
        child: ClipRRect(
          borderRadius: BorderRadius.circular(24),
          child: BackdropFilter(
            filter: ImageFilter.blur(sigmaX: 8, sigmaY: 8),
            child: Container(
              height: 48,
              color: Colors.black.withOpacity(0.3),
              child: Padding(
                padding: const EdgeInsets.symmetric(horizontal: 12),
                child: Row(
                  children: [
                    const Icon(
                      Icons.place,
                      color: Colors.white,
                    ),
                    const SizedBox(width: 4),
                    Text(
                      details.country.length > 10
                          ? '${details.country.substring(0, 10)}...'
                          : details.country,
                      style: const TextStyle(
                        color: Colors.white,
                        fontSize: 16,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: imageWidth,
      child: ClipRRect(
        borderRadius: BorderRadius.circular(32),
        child: Stack(
          fit: StackFit.expand,
          children: [
            image(),
            rating(),
            favoriteIcon(),
            bottomText(),
          ],
        ),
      ),
    );
  }

}

class Destination {
  final String city;
  final String country;
  final String rating;

  const Destination({
    required this.city,
    required this.country,
    required this.rating,
  });

// String get image => 'assets/images/${city.toLowerCase()}.jpg';
}

class MockAllDestinations {
  static const data = [
    Destination(city: 'https://images.unsplash.com/photo-1491557345352-5929e343eb89?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80', country: 'Bahamas', rating: '4.6'),
    Destination(city: 'https://images.unsplash.com/photo-1664215795139-516f3a4ce81b?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1229&q=80', country: 'Greece', rating: '4.8'),
    Destination(city: 'https://images.unsplash.com/photo-1664547401590-287057ac6eb5?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1169&q=80', country: 'Italy', rating: '4.4'),
    Destination(city: 'https://images.unsplash.com/photo-1664261421791-c25c5760f577?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80', country: 'England', rating: '4.5'),
  ];
}


تعليقات