mirror of
https://github.com/love2d/love-android.git
synced 2026-08-17 19:24:07 +02:00
Implement game selector.
Item selection is currently not implemented.
This commit is contained in:
@@ -0,0 +1,70 @@
|
|||||||
|
package org.love2d.android;
|
||||||
|
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class GameListAdapter extends RecyclerView.Adapter<GameListAdapter.ViewHolder> {
|
||||||
|
|
||||||
|
private Data[] data = null;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
|
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_game, parent, false);
|
||||||
|
ViewHolder holder = new ViewHolder(view);
|
||||||
|
|
||||||
|
return holder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||||
|
Data data = this.data[position];
|
||||||
|
holder.setName(data.path.getName());
|
||||||
|
holder.setIsDirectory(data.directory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return data != null ? data.length : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(Data[] data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
|
private final TextView name;
|
||||||
|
private final ImageView image;
|
||||||
|
|
||||||
|
public ViewHolder(View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
|
||||||
|
name = itemView.findViewById(R.id.textView);
|
||||||
|
image = itemView.findViewById(R.id.imageView);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name.setText(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsDirectory(boolean directory) {
|
||||||
|
this.image.setImageResource(directory ? R.drawable.ic_baseline_folder_32 : R.drawable.ic_baseline_insert_drive_file_32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Data {
|
||||||
|
// Absolute path of the file.
|
||||||
|
public File path;
|
||||||
|
// Denote if this game is a directory.
|
||||||
|
public boolean directory;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,9 @@ package org.love2d.android;
|
|||||||
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -10,19 +13,40 @@ import android.os.Bundle;
|
|||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.zip.ZipFile;
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity {
|
public class MainActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
private Executor executor = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_main);
|
setContentView(R.layout.activity_main);
|
||||||
|
|
||||||
|
RecyclerView recyclerView = findViewById(R.id.recyclerView);
|
||||||
SwipeRefreshLayout swipeLayout = findViewById(R.id.swipeRefreshLayout);
|
SwipeRefreshLayout swipeLayout = findViewById(R.id.swipeRefreshLayout);
|
||||||
|
ConstraintLayout noGameText = findViewById(R.id.constraintLayout);
|
||||||
|
|
||||||
|
GameListAdapter adapter = new GameListAdapter();
|
||||||
|
|
||||||
|
// Set refresh listener
|
||||||
swipeLayout.setOnRefreshListener(() -> {
|
swipeLayout.setOnRefreshListener(() -> {
|
||||||
// TODO: Actually update list of games
|
scanGames(adapter, noGameText, swipeLayout);
|
||||||
swipeLayout.setRefreshing(false);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Set layout manager and adapter
|
||||||
|
recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
|
||||||
|
recyclerView.setAdapter(adapter);
|
||||||
|
|
||||||
|
scanGames(adapter, noGameText, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -69,4 +93,93 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
return builder.setMessage(message.toString()).create();
|
return builder.setMessage(message.toString()).create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void scanGames(GameListAdapter adapter, ConstraintLayout noGameText, SwipeRefreshLayout swipeRefreshLayout) {
|
||||||
|
final MainActivity current = this;
|
||||||
|
|
||||||
|
executor.execute(() -> {
|
||||||
|
File extDir = getExternalFilesDir("games");
|
||||||
|
|
||||||
|
if (!extDir.isDirectory()) {
|
||||||
|
if (!extDir.mkdir()) {
|
||||||
|
// Scan failure, abort
|
||||||
|
if (swipeRefreshLayout != null) {
|
||||||
|
swipeRefreshLayout.setRefreshing(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
new AlertDialog.Builder(current)
|
||||||
|
.setTitle("Scan error")
|
||||||
|
.setMessage("Scan failure")
|
||||||
|
.setPositiveButton(R.string.ok, (dialog1, which) -> { })
|
||||||
|
.create()
|
||||||
|
.show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<GameListAdapter.Data> validGames = new ArrayList<>();
|
||||||
|
File[] files = extDir.listFiles();
|
||||||
|
|
||||||
|
if (files != null) {
|
||||||
|
for (File file: files) {
|
||||||
|
GameListAdapter.Data gameData = null;
|
||||||
|
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
if (isValidGamedir(file)) {
|
||||||
|
gameData = new GameListAdapter.Data();
|
||||||
|
gameData.path = file;
|
||||||
|
gameData.directory = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isValidLovegame(file)) {
|
||||||
|
gameData = new GameListAdapter.Data();
|
||||||
|
gameData.path = file;
|
||||||
|
gameData.directory = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gameData != null) {
|
||||||
|
validGames.add(gameData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean empty = validGames.isEmpty();
|
||||||
|
|
||||||
|
runOnUiThread(() -> {
|
||||||
|
if (empty) {
|
||||||
|
adapter.setData(null);
|
||||||
|
} else {
|
||||||
|
GameListAdapter.Data[] gameDatas = new GameListAdapter.Data[validGames.size()];
|
||||||
|
validGames.toArray(gameDatas);
|
||||||
|
adapter.setData(gameDatas);
|
||||||
|
}
|
||||||
|
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
|
||||||
|
if (swipeRefreshLayout != null) {
|
||||||
|
swipeRefreshLayout.setRefreshing(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
noGameText.setVisibility(empty ? View.VISIBLE : View.INVISIBLE);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isValidLovegame(File file) {
|
||||||
|
boolean valid = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
ZipFile zip = new ZipFile(file, ZipFile.OPEN_READ);
|
||||||
|
valid = zip.getEntry("main.lua") != null;
|
||||||
|
zip.close();
|
||||||
|
} catch (IOException ignored) { }
|
||||||
|
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isValidGamedir(File file) {
|
||||||
|
File mainLua = new File(file, "main.lua");
|
||||||
|
return mainLua.isFile();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/recyclerView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:listitem="@layout/row_game">
|
tools:listitem="@layout/row_game">
|
||||||
@@ -20,6 +21,7 @@
|
|||||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/constraintLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="8dp"
|
android:padding="8dp"
|
||||||
|
|||||||
Reference in New Issue
Block a user