Home Android News App Flutter

News App Flutter

0
News App Flutter

Halo teman Flutter! Pada artikel kali ini saya ingin membahas tentang “News App Flutter”.

  1. Buat database dengan nama berita_coba, kemudian insert dengan isi berita yang ada di internet.

2. Buat folder didalam htdocs kemudian import gambar berita yang akan ditampilkan.

3. Buat file koneksi.php di Visual Studio Code.

<?php

$koneksi = mysqli_connect("localhost","root","","berita_coba");

if($koneksi) {

} else {
    echo "Gagal";
}
?>

4. Buat file getBerita.php di Visual Studio Code.

<?php

include "koneksi.php";

$sql = "SELECT * FROM tb_coba";

$result = $koneksi->query($sql);

if($result->num_rows > 0 ) {
    $res['sukses'] = true;
    $res['pesan'] = "Berhasil Menampilkan Berita";
    $res['data'] = array();
    while ($row = $result->fetch_assoc()) {
        $res['data'][] = $row;
    }

} else {
    $res['sukses'] = false;
    $res['pesan'] = "Gagal Menampilkan Berita";
    $res['data'] = null;
}

echo json_encode($res);

?>

5. Kemudian getBerita di postman dengan format json

6. Kemudian copy ke https://quicktype.io/. dan masuk ke dalam project flutter. Buat dengan nama file res_get_berita.dart

// To parse this JSON data, do
//
//     final resGetBerita = resGetBeritaFromJson(jsonString);

import 'dart:convert';

ResGetBerita resGetBeritaFromJson(String str) =>
    ResGetBerita.fromJson(json.decode(str));

String resGetBeritaToJson(ResGetBerita data) => json.encode(data.toJson());

class ResGetBerita {
  ResGetBerita({
    this.sukses,
    this.pesan,
    this.data,
  });

  bool? sukses;
  String? pesan;
  List<Datum>? data;

  factory ResGetBerita.fromJson(Map<String, dynamic> json) => ResGetBerita(
        sukses: json["sukses"] == null ? null : json["sukses"],
        pesan: json["pesan"] == null ? null : json["pesan"],
        data: json["data"] == null
            ? null
            : List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
      );

  Map<String, dynamic> toJson() => {
        "sukses": sukses == null ? null : sukses,
        "pesan": pesan == null ? null : pesan,
        "data": data == null
            ? null
            : List<dynamic>.from(data!.map((x) => x.toJson())),
      };
}

class Datum {
  Datum({
    this.id,
    this.judulBerita,
    this.isiBerita,
    this.tglBerita,
    this.gambarBerita,
  });

  String? id;
  String? judulBerita;
  String? isiBerita;
  DateTime? tglBerita;
  String? gambarBerita;

  factory Datum.fromJson(Map<String, dynamic> json) => Datum(
        id: json["id"] == null ? null : json["id"],
        judulBerita: json["judul_berita"] == null ? null : json["judul_berita"],
        isiBerita: json["isi_berita"] == null ? null : json["isi_berita"],
        tglBerita: json["tgl_berita"] == null
            ? null
            : DateTime.parse(json["tgl_berita"]),
        gambarBerita:
            json["gambar_berita"] == null ? null : json["gambar_berita"],
      );

  Map<String, dynamic> toJson() => {
        "id": id == null ? null : id,
        "judul_berita": judulBerita == null ? null : judulBerita,
        "isi_berita": isiBerita == null ? null : isiBerita,
        "tgl_berita": tglBerita == null
            ? null
            : "${tglBerita!.year.toString().padLeft(4, '0')}-${tglBerita!.month.toString().padLeft(2, '0')}-${tglBerita!.day.toString().padLeft(2, '0')}",
        "gambar_berita": gambarBerita == null ? null : gambarBerita,
      };
}

7. Kemudian buat project baru dengan nama NewsAppFlutter, lalu create file baru dengan nama constant.dart.

const String BaseUrl = "http://192.168.10.17/berita_coba/";
const String ImageUrl = "http://192.168.10.17/berita_coba/";

8. Selanjutnya masuk kedalam UI, create file baru dengan nama news_page.dart

import 'package:flutter/material.dart';
import 'package:flutter_news_api/constant.dart';
import 'package:flutter_news_api/detailpage.dart';
import 'package:flutter_news_api/res_get_berita.dart';
import 'package:http/http.dart' as http;
import 'package:carousel_slider/carousel_slider.dart';

class NewsPage extends StatefulWidget {
  const NewsPage({Key? key}) : super(key: key);

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

class _NewsPageState extends State<NewsPage> {
  List<Datum>? listBerita = [];
  Future getListBerita() async {
    var res = await http
        .get(Uri.parse('http://192.168.10.17/berita_coba/getBerita.php'));
    setState(() {
      listBerita = resGetBeritaFromJson(res.body).data;
    });
    return resGetBeritaFromJson(res.body).data;
  }

  @override
  void initState() {
    getListBerita();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
          backgroundColor: Colors.black,
          title: Text(
            "News Application",
            style: TextStyle(
                fontSize: 18, color: Colors.white, fontWeight: FontWeight.w700),
          ),
          centerTitle: true,
        ),
        backgroundColor: Colors.white,
        body: SingleChildScrollView(
          physics: NeverScrollableScrollPhysics(),
          child: Column(
            children: [
              //mempunyai beberapa parameter
              CarouselSlider(
                items: listBerita!.map((e) {
                  return Image.network('$ImageUrl' + e.gambarBerita!);
                }).toList(),
                options:
                    CarouselOptions(autoPlay: true, enlargeCenterPage: true),
              ),
              Container(
                height: 330,
                child: ListView.builder(
                    shrinkWrap: true,
                    itemCount: listBerita!.length,
                    itemBuilder: (context, index) {
                      Datum? data = listBerita![index];
                      return Card(
                        child: ListTile(
                          onTap: () {
                            Navigator.push(
                                context,
                                MaterialPageRoute(
                                    builder: (context) => DetailPage(data)));
                          },
                          title: Text(
                            '${data.judulBerita}',
                            style: TextStyle(fontWeight: FontWeight.w700),
                          ),
                          contentPadding: EdgeInsets.all(10),
                          subtitle: Text(
                            '\n${data.isiBerita}',
                            style: TextStyle(fontWeight: FontWeight.normal),
                          ),
                          leading: Padding(
                            padding: EdgeInsets.all(8),
                            child: ClipRRect(
                              borderRadius: BorderRadius.circular(15),
                              child: Image.network(
                                '$ImageUrl' + data.gambarBerita!,
                                width: 100,
                                height: 100,
                                fit: BoxFit.cover,
                              ),
                            ),
                          ),
                        ),
                      );
                    }),
              ),
              SizedBox(height: 20),
            ],
          ),
        ),
      ),
    );
  }
}

9. Tambahkan file baru dengan create file bottom_navigation.dart untuk project NewsApp Flutter

import 'package:flutter/material.dart';
import 'package:flutter_news_api/menu.dart';
import 'package:flutter_news_api/news_page.dart';

class BottomNavigation extends StatefulWidget {
  const BottomNavigation({Key? key}) : super(key: key);

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

class _BottomNavigationState extends State<BottomNavigation> {
  int _selectednavBar = 0;
  void _changeselectedNavBar(int index) {
    setState(() {
      _selectednavBar = index;
    });
  }

  final _widgetOptions = [
    NewsPage(),
    Menu(),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _widgetOptions[_selectednavBar],
      bottomNavigationBar: BottomNavigationBar(
        showSelectedLabels: false,
        showUnselectedLabels: false,
        selectedItemColor: Colors.white,
        unselectedItemColor: Colors.grey,
        type: BottomNavigationBarType.fixed,
        onTap: _changeselectedNavBar,
        backgroundColor: Colors.black,
        currentIndex: _selectednavBar,
        items: [
          BottomNavigationBarItem(
              icon: Icon(
                Icons.menu_book,
                size: 20,
              ),
              activeIcon: Icon(
                Icons.menu_book,
                color: Colors.white,
                size: 20,
              ),
              label: 'News'),
          BottomNavigationBarItem(
              icon: Icon(
                Icons.account_balance_sharp,
                size: 20,
              ),
              activeIcon: Icon(
                Icons.account_balance_sharp,
                size: 20,
                color: Colors.white,
              ),
              label: 'Menu'),
        ],
      ),
    );
  }
}

10. Kemudian create file baru dengan nama menu.dart berfungsi untuk menampilkan berita dalam bentuk gridView

import 'package:flutter/material.dart';
import 'package:flutter_news_api/constant.dart';
import 'package:flutter_news_api/detailpage.dart';
import 'package:flutter_news_api/res_get_berita.dart';
import 'package:http/http.dart' as http;

class Menu extends StatefulWidget {
  const Menu({Key? key}) : super(key: key);

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

class _MenuState extends State<Menu> {
  List<Datum>? listBerita = [];
  Future getListBerita() async {
    var res = await http
        .get(Uri.parse('http://192.168.10.17/berita_coba/getBerita.php'));
    setState(() {
      listBerita = resGetBeritaFromJson(res.body).data;
    });
    return resGetBeritaFromJson(res.body).data;
  }

  @override
  void initState() {
    getListBerita();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        backgroundColor: Colors.white,
        appBar: AppBar(
          backgroundColor: Colors.black,
          title: Text('Menu Berita'),
          centerTitle: true,
        ),
        body: Column(
          children: [
            Flexible(
              child: Container(
                decoration:
                    BoxDecoration(borderRadius: BorderRadius.circular(8)),
                child: GridView.builder(
                    itemCount: listBerita!.length,
                    gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                        crossAxisCount: 2),
                    itemBuilder: (context, index) {
                      Datum? data = listBerita![index];
                      return InkWell(
                          child: Card(
                            color: Colors.white,
                            child: Padding(
                              padding: EdgeInsets.all(8),
                              child: GridTile(
                                footer: Container(
                                  alignment: Alignment.center,
                                  height: 50,
                                  color: Colors.black.withOpacity(0.5),
                                  child: Padding(
                                    padding: const EdgeInsets.only(
                                        left: 5, right: 5),
                                    child: Text(
                                      "${data.judulBerita}",
                                      style: TextStyle(
                                          fontSize: 12,
                                          fontWeight: FontWeight.w600,
                                          color: Colors.white),
                                    ),
                                  ),
                                ),
                                child: ClipRRect(
                                  borderRadius: BorderRadius.circular(8),
                                  child: Image.network(
                                    '$ImageUrl' + data.gambarBerita!,
                                    width: 100,
                                    height: 100,
                                    fit: BoxFit.cover,
                                  ),
                                ),
                              ),
                            ),
                          ),
                          onTap: () {
                            Navigator.push(
                                context,
                                MaterialPageRoute(
                                    builder: (context) => DetailPage(data)));
                          });
                    }),
              ),
            )
          ],
        ),
      ),
    );
  }
}

11. Terakhir create file detailpage.dart untuk menampilkan detail berita ketika di klik.

import 'package:flutter/material.dart';
import 'package:flutter_news_api/constant.dart';
import 'package:flutter_news_api/res_get_berita.dart';

class DetailPage extends StatelessWidget {
  final Datum data;
  DetailPage(this.data);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.black,
        title: Text(
          "Detail Berita",
          style: TextStyle(
              color: Colors.white, fontWeight: FontWeight.w500, fontSize: 20),
        ),
      ),
      body: Padding(
        padding: EdgeInsets.all(15),
        child: ListView(
          children: [
            ClipRRect(
              borderRadius: BorderRadius.circular(25),
              child: Image.network('$ImageUrl' + data.gambarBerita!),
            ),
            SizedBox(
              height: 20,
            ),
            Text(
              '${data.judulBerita}',
              style: TextStyle(fontSize: 18, fontWeight: FontWeight.w700),
            ),
            SizedBox(
              height: 10,
            ),
            Text(
              '${data.isiBerita}',
              style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400),
              textAlign: TextAlign.justify,
            )
          ],
        ),
      ),
    );
  }
}

Berikut hasil running :

news page
menu page
detail page