DEV Community

Cover image for World Cup 2026: I Built the Best Way to View Knockout Brackets on Android
Emil
Emil

Posted on

World Cup 2026: I Built the Best Way to View Knockout Brackets on Android

Displaying a tournament bracket on mobile is surprisingly hard. You need to handle variable-depth trees, connect matches with lines, scale everything to the screen, and make it scrollable. I couldn't find a good Android-native solution, so I built one.

Meet TournamentBracketLib — a lightweight Android library that takes structured match data and renders a full knockout bracket with connectors, animations, and now: team images and match labels.


What does it look like?

Here's a real-world example — the FIFA World Cup 2026 knockout stage, rendered entirely from live API data:

Knockout Brackets

16 matches in the Round of 32, funneling down to a single Final. Each cell shows team flags, scores (or "-" for unplayed matches), and match identifiers.


The Core Idea: 3 Simple Models

The API surface is intentionally minimal. You describe your tournament with three objects:

1. CompetitorData — A team or player

CompetitorData brazil = new CompetitorData("Brazil", "2");
brazil.setImageUrl("https://flagcdn.com/w80/br.png");
Enter fullscreen mode Exit fullscreen mode

Just a name, a score, and an optional image URL. That's it.

2. MatchData — A single match

MatchData match = new MatchData(brazil, argentina);
match.setMatchName("QF - Match 97");
Enter fullscreen mode Exit fullscreen mode

Two competitors face off. Add a label to identify the match in the bracket.

3. ColomnData — A round

ColomnData quarterFinals = new ColomnData(Arrays.asList(qf1, qf2, qf3, qf4));
ColomnData semiFinals = new ColomnData(Arrays.asList(sf1, sf2));
ColomnData finals = new ColomnData(Arrays.asList(finalMatch));
Enter fullscreen mode Exit fullscreen mode

Each column represents one round. The library draws connectors between adjacent columns automatically.

Render it

bracketsView.setBracketsData(Arrays.asList(quarterFinals, semiFinals, finals));
Enter fullscreen mode Exit fullscreen mode

One line. The library handles layout, scrolling, connector lines, and animations.


XML Setup

Drop a BracketsView into your layout with customizable colors:

<com.ventura.bracketslib.BracketsView
    android:id="@+id/bracket_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:bracketBackgroundColor="#1c222e"
    app:bracketColor="#262e40"
    app:bracketTextColor="#fff" />
Enter fullscreen mode Exit fullscreen mode

Dark mode, light mode, team colors — style it however you want.


Real-World Usage: World Cup 2026 App

To demonstrate the library, I built a full app that fetches live World Cup 2026 data and displays:

  • Knockout brackets — R32 through the Final, with country flags and match names
  • Group standings — All 12 groups with MP/W/D/L/GF/GA/GD/PTS tables
  • Pull-to-refresh — Swipe to reload live standings
Home Brackets Group Standings
Home Brackets Standings

The bracket data is fetched dynamically from a public API. Games are grouped by type (r32, r16, qf, sf, final), sorted by ID, and rendered — zero hardcoded match IDs.

// Dynamic bracket building — adapts to any tournament structure
Map<String, List<WorldCupGame>> gamesByType = new HashMap<>();
for (WorldCupGame game : games) {
    gamesByType.computeIfAbsent(game.getType(), k -> new ArrayList<>()).add(game);
}

String[] rounds = {"r32", "r16", "qf", "sf", "final"};
for (String round : rounds) {
    List<WorldCupGame> roundGames = gamesByType.get(round);
    Collections.sort(roundGames, (a, b) -> Integer.compare(a.getId(), b.getId()));
    // build MatchData list, add ColomnData to bracket
}
Enter fullscreen mode Exit fullscreen mode

If the API adds or removes matches tomorrow, the app adapts automatically.


How to Add It to Your Project

Step 1: Add JitPack to your repositories:

allprojects {
    repositories {
        google()
        mavenCentral()
        maven { url 'https://jitpack.io' }
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Add the dependency:

dependencies {
    implementation 'com.github.emil-ep:TournamentBracketLib:1.1.4'
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Add a BracketsView to your XML, build your data, call setBracketsData(). Done.


Use Cases

This isn't just for football. Anywhere you have elimination-style competition:

  • ⚽ Sports apps (football, basketball, tennis, cricket)
  • 🎮 Esports tournament trackers
  • 🏈 Fantasy league playoff displays
  • 💻 Hackathon competition brackets
  • 🎯 Any single/double elimination format

Tech Stack (Demo App)

Library Purpose
TournamentBracketLib Bracket rendering
Retrofit + Gson API calls
Glide Flag image loading with caching
SwipeRefreshLayout Pull-to-refresh
DiffUtil Efficient RecyclerView updates

What's Next

  • Tap-to-expand match details
  • Losers bracket (double elimination) support
  • Jetpack Compose version

⭐ If this is useful to you...

I'd really appreciate a star — it helps other developers discover the project:

👉 Star TournamentBracketLib — The library

👉 Star TournamentBrackets — The World Cup 2026 demo app


Links


What features would you want in a bracket library? Drop a comment — I'm actively developing this and would love your input! 🙌

Top comments (0)