basic feed

This commit is contained in:
Benedek László 2024-05-04 18:02:41 +02:00
parent 42cae1ad9c
commit 87c76e2614
19 changed files with 408 additions and 1 deletions

View File

@ -35,6 +35,7 @@ android {
}
buildFeatures {
compose true
viewBinding true
}
composeOptions {
kotlinCompilerExtensionVersion '1.5.1'
@ -59,6 +60,8 @@ dependencies {
implementation libs.ui.graphics
implementation libs.ui.tooling.preview
implementation libs.material3
implementation libs.legacy.support.v4
implementation libs.recyclerview
testImplementation libs.junit
androidTestImplementation libs.ext.junit
androidTestImplementation libs.espresso.core

View File

@ -0,0 +1,72 @@
package com.dowerx.quack;
import android.content.Context;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.dowerx.quack.model.Post;
/**
* A fragment representing a list of Items.
*/
public class FeedFragment extends Fragment {
// TODO: Customize parameter argument names
private static final String ARG_COLUMN_COUNT = "column-count";
// TODO: Customize parameters
private int mColumnCount = 1;
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public FeedFragment() {
}
// TODO: Customize parameter initialization
@SuppressWarnings("unused")
public static FeedFragment newInstance(int columnCount) {
FeedFragment fragment = new FeedFragment();
Bundle args = new Bundle();
args.putInt(ARG_COLUMN_COUNT, columnCount);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mColumnCount = getArguments().getInt(ARG_COLUMN_COUNT);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_feed_list, container, false);
// Set the adapter
if (view instanceof RecyclerView) {
Context context = view.getContext();
RecyclerView recyclerView = (RecyclerView) view;
if (mColumnCount <= 1) {
recyclerView.setLayoutManager(new LinearLayoutManager(context));
} else {
recyclerView.setLayoutManager(new GridLayoutManager(context, mColumnCount));
}
// TODO: get posts
recyclerView.setAdapter(new PostRecyclerViewAdapter(Post.ITEMS));
}
return view;
}
}

View File

@ -25,6 +25,8 @@ public class MainActivity extends AppCompatActivity {
}
public void login(View view) {
// TODO: login
startActivity(new Intent(this, SwitcherActivity.class));
}
public void redirect_register(View view) {

View File

@ -0,0 +1,57 @@
package com.dowerx.quack;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.TextView;
import com.dowerx.quack.databinding.FragmentPostBinding;
import com.dowerx.quack.model.Post;
import java.util.List;
public class PostRecyclerViewAdapter extends RecyclerView.Adapter<PostRecyclerViewAdapter.ViewHolder> {
private final List<Post> mValues;
public PostRecyclerViewAdapter(List<Post> items) {
mValues = items;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ViewHolder(FragmentPostBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mItem = mValues.get(position);
holder.username.setText(holder.mItem.getUser().getUsername());
holder.content.setText(holder.mItem.getContent());
}
@Override
public int getItemCount() {
return mValues.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public final TextView username;
public final TextView content;
public Post mItem;
public ViewHolder(@NonNull FragmentPostBinding binding) {
super(binding.getRoot());
username = binding.username;
content = binding.content;
}
@NonNull
@Override
public String toString() {
return super.toString() + " '" + content.getText() + "'";
}
}
}

View File

@ -25,6 +25,7 @@ public class RegisterActivity extends AppCompatActivity {
}
public void register(View view) {
// TODO: register
}
public void redirect_login(View view) {

View File

@ -1,14 +1,19 @@
package com.dowerx.quack;
import android.os.Bundle;
import android.view.MenuItem;
import androidx.activity.EdgeToEdge;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.fragment.app.Fragment;
public class SwitcherActivity extends AppCompatActivity {
import com.google.android.material.navigation.NavigationBarView;
public class SwitcherActivity extends AppCompatActivity implements NavigationBarView.OnItemSelectedListener, NavigationBarView.OnItemReselectedListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -20,5 +25,29 @@ public class SwitcherActivity extends AppCompatActivity {
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
((NavigationBarView)findViewById(R.id.bottom_nav_bar)).setOnItemSelectedListener(this);
((NavigationBarView)findViewById(R.id.bottom_nav_bar)).setOnItemReselectedListener(this);
loadFragment(new FeedFragment());
}
@Override
public void onNavigationItemReselected(@NonNull MenuItem menuItem) {
}
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
return false;
}
private void loadFragment(Fragment fragment) {
if (fragment != null) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.main_fragment_holder, fragment)
.commit();
}
}
}

View File

@ -0,0 +1,81 @@
package com.dowerx.quack.model;
import java.sql.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Post {
public static final List<Post> ITEMS;
static {
ITEMS = Arrays.asList(
new Post(new User("username 1", "exmaple@example.com", "random_id"), "some content", null, 69, false, "random post id"),
new Post(new User("username 1", "exmaple@example.com", "random_id"), "some content", null, 69, false, "random post id")
);
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public int getLikes() {
return likes;
}
public void setLikes(int likes) {
this.likes = likes;
}
public boolean isLiked() {
return liked;
}
public void setLiked(boolean liked) {
this.liked = liked;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Post(User user, String content, String image, int likes, boolean liked, String id) {
this.user = user;
this.content = content;
this.image = image;
this.likes = likes;
this.liked = liked;
this.id = id;
}
private User user;
private String content;
private String image;
private int likes;
private boolean liked;
private String id;
}

View File

@ -0,0 +1,37 @@
package com.dowerx.quack.model;
public class User {
public User(String username, String email, String id) {
this.username = username;
this.email = email;
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
private String username;
private String email;
private String id;
}

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M8,8H6v7c0,1.1 0.9,2 2,2h9v-2H8V8z"/>
<path android:fillColor="@android:color/white" android:pathData="M20,3h-8c-1.1,0 -2,0.9 -2,2v6c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V5C22,3.9 21.1,3 20,3zM20,11h-8V7h8V11z"/>
<path android:fillColor="@android:color/white" android:pathData="M4,12H2v7c0,1.1 0.9,2 2,2h9v-2H4V12z"/>
</vector>

View File

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M17,19.22H5V7h7V5H5C3.9,5 3,5.9 3,7v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2v-7h-2V19.22z"/>
<path android:fillColor="@android:color/white" android:pathData="M19,2h-2v3h-3c0.01,0.01 0,2 0,2h3v2.99c0.01,0.01 2,0 2,0V7h3V5h-3V2z"/>
<path android:fillColor="@android:color/white" android:pathData="M7,9h8v2h-8z"/>
<path android:fillColor="@android:color/white" android:pathData="M7,12l0,2l8,0l0,-2l-3,0z"/>
<path android:fillColor="@android:color/white" android:pathData="M7,15h8v2h-8z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M11.99,2c-5.52,0 -10,4.48 -10,10s4.48,10 10,10 10,-4.48 10,-10 -4.48,-10 -10,-10zM15.6,8.34c1.07,0 1.93,0.86 1.93,1.93 0,1.07 -0.86,1.93 -1.93,1.93 -1.07,0 -1.93,-0.86 -1.93,-1.93 -0.01,-1.07 0.86,-1.93 1.93,-1.93zM9.6,6.76c1.3,0 2.36,1.06 2.36,2.36 0,1.3 -1.06,2.36 -2.36,2.36s-2.36,-1.06 -2.36,-2.36c0,-1.31 1.05,-2.36 2.36,-2.36zM9.6,15.89v3.75c-2.4,-0.75 -4.3,-2.6 -5.14,-4.96 1.05,-1.12 3.67,-1.69 5.14,-1.69 0.53,0 1.2,0.08 1.9,0.22 -1.64,0.87 -1.9,2.02 -1.9,2.68zM11.99,20c-0.27,0 -0.53,-0.01 -0.79,-0.04v-4.07c0,-1.42 2.94,-2.13 4.4,-2.13 1.07,0 2.92,0.39 3.84,1.15 -1.17,2.97 -4.06,5.09 -7.45,5.09z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
</vector>

View File

@ -7,4 +7,25 @@
android:layout_height="match_parent"
tools:context=".SwitcherActivity">
<FrameLayout
android:id="@+id/main_fragment_holder"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/bottom_nav_bar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:labelVisibilityMode="labeled"
app:menu="@menu/switcher_menu"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/list"
android:name="com.dowerx.quack.FeedFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
app:layoutManager="LinearLayoutManager"
tools:context=".FeedFragment"
tools:listitem="@layout/fragment_post" />

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/placeholder_name"
android:layout_marginTop="20dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.10"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="some random placeeholder post content"
app:layout_constraintTop_toBottomOf="@+id/username"
android:layout_margin="20dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:icon="@drawable/feed"
android:title="@string/feed"
android:id="@+id/nav_feed"/>
<item
android:icon="@drawable/search"
android:title="@string/search"
android:id="@+id/nav_search"/>
<item
android:icon="@drawable/post"
android:title="@string/post"
android:id="@+id/nav_post"/>
<item
android:icon="@drawable/profile"
android:title="@string/profile"
android:id="@+id/nav_profile"/>
</menu>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="text_margin">16dp</dimen>
</resources>

View File

@ -7,4 +7,9 @@
<string name="title_activity_register">RegisterActivity</string>
<string name="username_hint">Username</string>
<string name="repeat_password_hint">Repeat Password</string>
<string name="feed">Feed</string>
<string name="post">Post</string>
<string name="profile">Profile</string>
<string name="search">Search</string>
<string name="placeholder_name">placeholder_name</string>
</resources>

View File

@ -11,6 +11,8 @@ kotlin = "1.9.0"
lifecycleRuntimeKtx = "2.7.0"
activityCompose = "1.9.0"
composeBom = "2023.08.00"
legacySupportV4 = "1.0.0"
recyclerview = "1.3.0"
[libraries]
junit = { group = "junit", name = "junit", version.ref = "junit" }
@ -30,6 +32,8 @@ ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview
ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
material3 = { group = "androidx.compose.material3", name = "material3" }
legacy-support-v4 = { group = "androidx.legacy", name = "legacy-support-v4", version.ref = "legacySupportV4" }
recyclerview = { group = "androidx.recyclerview", name = "recyclerview", version.ref = "recyclerview" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }