Create listview.builder in Flutter || Flutter Call list UI

In this post, we’ll walk through how to build a Listview in flutter using ListView.builder This screen shows detailed information about past calls in a clean, scrollable list format.  Let’s dive into the main component that handles this list – the ListView.builder.

What is Listview Builder ?

Whenever we need to display a long or dynamic list in an app — like a chat list, call history, list of users, etc. — the most effective method in Flutter is: ListView.builder.
Now the question is how is this ListView.builder different from other list builder methods? And why is it so popular? Let’s understand it in-depth.

ListView.builder is the solution to this problem.
It creates (renders) only the items that are visible on the screen at the moment. As the user scrolls, the next items are loaded. This makes better use of both memory and performance.

InvestmentScreen.dart
  
       
       
       import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';

import '../../../provider/calling_provider.dart';
import '../../../provider/profile_provider.dart';
import '../../../util/color_resources.dart';
import '../../../util/custom_themes.dart';
import '../../../util/dimensions.dart';
import '../chat/widget/message_item_widget.dart';
import 'calling_chat_screen.dart';

class CallHistoryScreen extends StatefulWidget {
  final bool isAppBarVisible;
  const CallHistoryScreen({super.key, this.isAppBarVisible=true});

  @override
  State createState() => _CallHistoryScreenState();
}

class _CallHistoryScreenState extends State {
  final RefreshController callHistoryRefreshController =
      RefreshController(initialRefresh: true);

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      //getData();
    });
  }

  @override
  Widget build(BuildContext context) {
    int id = Provider.of(context, listen: false).profileResponse?.profile.id ?? 0;
    return Scaffold(
      appBar: widget.isAppBarVisible ? AppBar(
        backgroundColor: ColorResources.themeColor,
        title: const Text('Call History'),
      ): null,
      body: Consumer(
        builder: (context, callProvider, child) {
          return SmartRefresher(
            controller: callHistoryRefreshController,
            enablePullUp: true,
            onRefresh: () async {
              final result =
                  await callProvider.getCallHistoryList(isRefresh: true);
              if (result) {
                callHistoryRefreshController.refreshCompleted();
              } else {
                callHistoryRefreshController.refreshFailed();
              }
            },
            onLoading: () async {
              final result = await callProvider.getCallHistoryList();
              if (result) {
                callHistoryRefreshController.loadComplete();
              } else {
                callHistoryRefreshController.loadComplete();
              }
            },
            child: callProvider.isLoading
                ? Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      callProvider.isLoading
                          ? const Center(
                              child: CircularProgressIndicator(
                              color: ColorResources.themeColor,
                            ))
                          : Text(callProvider.message)
                    ],
                  )
                : callProvider.callList.isEmpty
                    ? Center(child: Text(callProvider.message))
                    : ListView.builder(
                        itemCount: callProvider.callList.length,
                        itemBuilder: (context, index) {
                          var callData = callProvider.callList[index];
                          int sec = int.parse(callData.callTime) % 60;
                          int min = (int.parse(callData.callTime) / 60).floor();
                          String minute = min.toString().length <= 1 ? "0$min" : "$min";
                          String second = sec.toString().length <= 1 ? "0$sec" : "$sec";
                          return InkWell(
                            onTap: (){
                              callProvider.setCallerNamePhoto(callData.callerUser.name, callData.callerUser.photo);
                              Navigator.push(context, MaterialPageRoute(builder: (context)=>CallingChatScreen(callerId: callData.id.toString())));
                            },
                            child: Container(
                              margin: EdgeInsets.all(10),
                              decoration: BoxDecoration(
                                borderRadius: BorderRadius.circular(10),
                                    border: Border.all( color: Colors.grey,   width: 0.1)
                              ),
                              child: Padding(
                                padding: const EdgeInsets.all(8.0),
                                child: Column(
                                  children: [
                                    Row(
                                      children: [
                                        Icon(
                                          callData.callerUser.id == id
                                              ? Icons.call_end_outlined
                                              : Icons.call_missed,
                                          color: callData.callerUser.id == id
                                              ? Colors.green
                                              : Colors.red,
                                        ),
                                        Expanded(
                                          child: Row(
                                            mainAxisAlignment:
                                                MainAxisAlignment.spaceBetween,
                                            children: [
                                              Expanded(
                                                flex: 4,
                                                child: Column(
                                                  crossAxisAlignment:
                                                      CrossAxisAlignment.start,
                                                  children: [
                                                    Row(
                                                      mainAxisAlignment:
                                                          MainAxisAlignment
                                                              .spaceBetween,
                                                      children: [
                                                        Text(
                                                            "Call ${callData.callerUser.id == id ? 'to' : 'from'} ${callData.callerUser.id == id ? callData.receiverUser.name : callData.callerUser.name}",
                                                            style: TextStyle(fontWeight: FontWeight.w500,  )
                                                        ),
                                                        Text(
                                                            "$minute Min $second Sec",
                                                            style: const TextStyle(
                                                              fontSize: 13,
                                                                color: Colors.grey,
                                                                fontWeight: FontWeight.w400
                                                            )
                                                        )
                                                      ],
                                                    ),
                                                    const SizedBox(
                                                      height: 4,
                                                    ),
                                                    Row(
                                                      mainAxisAlignment:
                                                          MainAxisAlignment
                                                              .spaceBetween,
                                                      children: [
                                                        Text(
                                                          callData.createdAt,
                                                          style: const TextStyle(
                                                            fontSize: 11,
                                                              color: Colors.grey,
                                                              fontWeight: FontWeight.w400,


                                                          ),
                                                        ),
                                                        Text(
                                                            "Rs. ${callData.amount}",
                                                            style: const TextStyle(
                                                                fontSize: Dimensions
                                                                    .FONT_SIZE_SMALL))
                                                      ],
                                                    ),
                                                  ],
                                                ),
                                              ),
                                            ],
                                          ),
                                        )
                                      ],
                                    ),
                                    RowItem(title: "Name", content: '${callData.chatUserDetail?.firstName ?? "--"} ${callData.chatUserDetail?.lastName ?? "-"}'),
                                    RowItem(title: "DOB", content:  callData.chatUserDetail?.dob==null ? '--' :DateFormat('dd MMM yyyy').format(callData.chatUserDetail!.dob)),
                                    RowItem(title: "TOB", content: callData.chatUserDetail?.tob ?? "-"),
                                    RowItem(title: "POB", content: callData.chatUserDetail?.address ?? "-"),
                                    RowItem(title: "Call Start", content: callData.startTime,),
                                    RowItem(title: "Call End", content: callData.endTime,),
                                    //RowItem(title: "Duration", content: '${callData.duration} Min'),
                                    //RowItem(title: "Rate", content: '${callData.astrologerRate} / Min'),
                                    //RowItem(title: "Payment", content: '${callData.paymentType.toUpperCase()} '),
                                  ],
                                ),
                              ),
                            ),
                          );
                        }),
          );
        },
      ),
    );
  }
}

Code Explanation 

  • It uses the pull_to_refresh package so that the user can refresh or load more call history by pulling the screen down.
  • Its core part is a dynamic list, created using ListView.builder. This list makes the calling history scalable and performance-friendly.
  • Call history and profile data is managed from the Provider package, maintaining a strong connection between the UI and data.
  • Tapping on each call takes the user to the calling screen where further details and interactions can take place.
  • The details shown below each call are represented by a custom RowItem widget, keeping the code clean and reusable.


Conclusion 

This screen can become an important part of any calling or chat app. It incorporates many powerful technologies of Flutter like Provider, SmartRefresher, ListView.builder, and InkWell which make it rich and professional.

Output

 
Create listview.builder in Flutter

Post a Comment

0 Comments