-2

To summarize, I'm building a social media app that displays:

  1. A Newsfeed that shows posts from all user profiles in a given account
  2. A Timeline that shows posts from a specific user profile in the account

I've built a custom BaseAdapter to populate a custom cell within each ListView. The Newsfeed ListView (that populates posts from all users on the account) is populating correctly.

The Timeline ListView (that populates posts from one profile on the account) is not showing. I've set breakpoints to ensure that my ArrayList is not null or empty when populating the Timeline ListView. In addition, breakpoints verify that my custom adapter is, in fact, pulling data from the ArrayList and inflating cells. However, the ListView is simply not visible.

Here is the layout file for my Newsfeed fragment (that is working correctly):

<android.support.constraint.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="match_parent"
android:background="@color/colorSkyPrimary">

<android.support.constraint.ConstraintLayout
    android:id="@+id/constraintLayout"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:background="@android:color/white"
    android:elevation="16dp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.0"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent">

    <EditText
        android:id="@+id/input_post"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="32dp"
        android:layout_marginEnd="32dp"
        android:backgroundTint="@color/colorSkyPrimary"
        android:ems="10"
        android:gravity="start|top"
        android:hint="@string/what_s_going_on"
        android:importantForAutofill="no"
        android:inputType="textMultiLine"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:targetApi="o" />

    <ImageButton
        android:id="@+id/button_photo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:backgroundTint="@android:color/white"
        android:contentDescription="@string/camera_button"
        app:layout_constraintBottom_toBottomOf="@+id/input_post"
        app:layout_constraintEnd_toEndOf="@+id/input_post"
        app:srcCompat="@drawable/camera_icon" />

    <Button
        android:id="@+id/button_cancel"
        style="@style/Widget.AppCompat.Button.Borderless"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="48dp"
        android:layout_marginTop="8dp"
        android:text="@android:string/cancel"
        android:textColor="@color/colorGrassPrimary"
        android:visibility="gone"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/post_image" />

    <Button
        android:id="@+id/button_update"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="48dp"
        android:backgroundTint="@color/colorGrassPrimary"
        android:text="@string/update"
        android:textColor="@color/colorButtonText"
        android:visibility="gone"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/post_image" />

    <ImageView
        android:id="@+id/post_image"
        android:layout_width="0dp"
        android:layout_height="300dp"
        android:contentDescription="@string/post_image"
        android:scaleType="fitCenter"
        android:visibility="gone"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/input_post"
        tools:srcCompat="@tools:sample/avatars" />
</android.support.constraint.ConstraintLayout>

<ListView
    android:id="@+id/list_newsfeed"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintBottom_toTopOf="@+id/picker_image"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.0"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/constraintLayout"
    app:layout_constraintVertical_bias="0.0" />

<android.support.constraint.ConstraintLayout
    android:id="@+id/picker_image"
    android:layout_width="0dp"
    android:layout_height="75dp"
    android:background="@android:color/white"
    android:elevation="16dp"
    android:visibility="gone"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent">

    <android.support.constraint.Guideline
        android:id="@+id/guideline14"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.5" />

    <ImageButton
        android:id="@+id/button_camera"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="32dp"
        android:layout_marginBottom="8dp"
        android:background="@android:color/transparent"
        android:contentDescription="@string/camera_button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/guideline14"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/camera_icon_large" />

    <ImageButton
        android:id="@+id/button_gallery"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="32dp"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp"
        android:background="@android:color/transparent"
        android:contentDescription="@string/gallery_button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="@+id/guideline14"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.375"
        app:srcCompat="@drawable/gallery_icon" />
</android.support.constraint.ConstraintLayout>

Here is the layout file for my Profile fragment (in which the ListView is not showing at runtime)

<android.support.constraint.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="match_parent"
android:background="@color/colorSkyPrimary">

<android.support.constraint.ConstraintLayout
    android:id="@+id/constraintLayout4"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:background="@android:color/white"
    android:elevation="8dp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent">

    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/profile_photo"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginStart="32dp"
        android:layout_marginTop="32dp"
        android:src="@drawable/male_icon_large"
        app:civ_border_color="@android:color/transparent"
        app:civ_border_width="2dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/display_name"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="8dp"
        android:text="@string/brelynn_mack"
        android:textAlignment="viewStart"
        android:textColor="@color/colorTextDark"
        android:textSize="18sp"
        app:layout_constraintEnd_toStartOf="@+id/button_delete_profile"
        app:layout_constraintStart_toEndOf="@+id/profile_photo"
        app:layout_constraintTop_toTopOf="@+id/profile_photo" />

    <TextView
        android:id="@+id/display_timestamp"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"
        android:text="@string/may_14_2019_9_59_pm"
        android:textAlignment="viewStart"
        android:textColor="@color/colorTextLight"
        android:textSize="14sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/profile_photo"
        app:layout_constraintTop_toBottomOf="@+id/display_name" />

    <TextView
        android:id="@+id/display_last_location"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:text="@string/_8741_grouse_run_lane_28314"
        android:textAlignment="viewStart"
        android:textColor="@color/colorTextPrimary"
        android:textSize="12sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/profile_photo"
        app:layout_constraintTop_toBottomOf="@+id/display_timestamp" />

    <ImageButton
        android:id="@+id/button_delete_profile"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:background="@android:color/white"
        android:contentDescription="@string/trash_button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/trash_icon" />

    <ImageButton
        android:id="@+id/button_photo"
        android:layout_width="35dp"
        android:layout_height="35dp"
        android:layout_marginStart="8dp"
        android:layout_marginBottom="16dp"
        android:background="@android:color/white"
        android:contentDescription="@string/camera_button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="@+id/profile_photo"
        app:layout_constraintTop_toBottomOf="@+id/profile_photo"
        app:srcCompat="@drawable/camera_icon" />

    <ImageButton
        android:id="@+id/button_family"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:layout_marginBottom="8dp"
        android:background="@android:color/white"
        android:contentDescription="@string/family_button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:srcCompat="@drawable/family_icon_small" />

    <ImageButton
        android:id="@+id/button_gallery"
        android:layout_width="35dp"
        android:layout_height="35dp"
        android:layout_marginEnd="8dp"
        android:background="@android:color/transparent"
        android:contentDescription="@string/gallery_button"
        android:scaleType="fitCenter"
        app:layout_constraintEnd_toEndOf="@+id/profile_photo"
        app:layout_constraintTop_toBottomOf="@+id/profile_photo"
        app:srcCompat="@drawable/gallery_icon" />
</android.support.constraint.ConstraintLayout>

<ListView
    android:id="@+id/list_posts"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/constraintLayout4" />

Here is my custom adapter:

public class NewsfeedAdapter extends BaseAdapter {



// Class properties
private static final String TAG = "NewsfeedAdapter";

public static final String EXTRA_POSTS = "extra_posts";
public static final String EXTRA_POSITION = "extra_position";

private final Context context;
ArrayList<Post> posts;
Account account;



// Constructor
public NewsfeedAdapter(Context context, ArrayList<Post> posts, Account account) {
    this.context = context;
    this.posts = posts;
    this.account = account;
}



// System generated methods

@Override
public int getCount() {
    return posts.size();
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public Object getItem(int position) {
    return posts.get(position);
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    final Post post = posts.get(position);

    if(convertView == null) {
        LayoutInflater layoutInflater = LayoutInflater.from(context);
        convertView = layoutInflater.inflate(R.layout.cell_newsfeed, null);
    }

    TextView profileNameDisplay = convertView.findViewById(R.id.display_profile_name);
    String name = post.getPosterName() + " " + account.getFamilyName();
    profileNameDisplay.setText(name);

    TextView timestampDisplay = convertView.findViewById(R.id.display_timestamp);
    SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM dd, yyyy @ hh:mm a", Locale.getDefault());
    String timestamp = dateFormat.format(post.getTimeStamp());
    timestampDisplay.setText(timestamp);

    TextView postMessageDisplay = convertView.findViewById(R.id.display_post_message);
    postMessageDisplay.setText(post.getPostMessage());

    if (post.getHasImage()) {
        AccountUtils.loadProfilePhoto(context, convertView, post.getPosterId());
    }

    else {
        ImageView postImage = convertView.findViewById(R.id.display_post_image);
        postImage.setVisibility(View.GONE);
    }

    PostUtils.loadPostImage(convertView, post.getPostId());

    ImageButton deleteButton = convertView.findViewById(R.id.button_delete_post);
    ImageButton editButton = convertView.findViewById(R.id.button_edit_post);

    toggleButtons(post, editButton, deleteButton);

    deleteButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
            alertBuilder.setTitle(context.getString(R.string.delete_post));
            alertBuilder.setMessage(context.getString(R.string.delete_post_message));

            alertBuilder.setPositiveButton(context.getString(R.string.delete), new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    posts.remove(position);
                    PostUtils.deletePost(context, post.getPostId(), post.getPosterId());
                    notifyDataSetChanged();
                    PostUtils.listenForNews(context);
                }
            });

            alertBuilder.setNegativeButton(context.getString(R.string.cancel), null);

            AlertDialog alert = alertBuilder.create();
            alert.show();
        }
    });

    editButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent editIntent = new Intent(context, EditPostActivity.class);
            editIntent.putExtra(EXTRA_POSTS, posts);
            editIntent.putExtra(EXTRA_POSITION, position);

            context.startActivity(editIntent);
        }
    });

    return convertView;
}



// Custom methods
private void toggleButtons(Post post, ImageButton editButton, ImageButton deleteButton) {
    long twoMinutes = System.currentTimeMillis() - (2 * 60 * 1000);
    long fiveMinutes = System.currentTimeMillis() - (5 * 60 * 1000);

    if (post.getTimeStamp().getTime() < fiveMinutes) {
        editButton.setVisibility(View.GONE);
    }

    else {
        editButton.setVisibility(View.VISIBLE);
    }

    if (post.getTimeStamp().getTime() < twoMinutes) {
        deleteButton.setVisibility(View.GONE);
    }

    else {
        deleteButton.setVisibility(View.VISIBLE);
    }
}

Here are the lifecycle methods from the Newsfeed fragment that load my data and set the adapter:

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_newsfeed, container, false);

    PostUtils.listenForNews(getActivity());

    mPosts = PostUtils.loadNewsfeed(getActivity());

    mNewsfeed = view.findViewById(R.id.list_newsfeed);

    mImagePicker = view.findViewById(R.id.picker_image);
    mPhotoView = view.findViewById(R.id.post_image);

    AccountUtils.listenForUpdates(getActivity());

    setClickListener(view);
    setFocusListener(view);

    return view;
}

@Override
public void onResume() {
    super.onResume();

    mPosts = PostUtils.loadNewsfeed(getActivity());
    Account account = AccountUtils.loadAccount(getActivity());

    mNewsfeedAdapter = new NewsfeedAdapter(getActivity(), mPosts, account);
    mNewsfeed.setAdapter(mNewsfeedAdapter);
}

Here are the lifecycle methods from my Profile fragment where the same functionality should work for a slightly different set of data:

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_profile, container, false);

    try {
        if(getActivity().getIntent() != null && getActivity().getIntent().getAction().equals(FamilyProfileFragment.ACTION_EDIT_PROFILE)) {
            mEditingSelf = false;
            mIsParent = true;
            mProfile = (Profile) getActivity().getIntent().getSerializableExtra(FamilyProfileFragment.EXTRA_PROFILE);

            String selectedName = mProfile.getFirstName();
            String loadedName = AccountUtils.loadProfile(getActivity()).getFirstName();

            if(selectedName.equals(loadedName)) {
                mEditingSelf = true;
            }
        }

        else {
            mEditingSelf = true;
            mProfile = AccountUtils.loadProfile(getActivity());

            if(mProfile instanceof Parent) {
                mIsParent = true;
            }

            else {
                mIsParent = false;
            }
        }
    }

    catch (Exception e) {
        e.printStackTrace();

        mEditingSelf = true;
        mProfile = AccountUtils.loadProfile(getActivity());

        if(mProfile instanceof Parent) {
            mIsParent = true;
        }

        else {
            mIsParent = false;
        }
    }

    mAccount = AccountUtils.loadAccount(getActivity());
    AccountUtils.loadProfilePhoto(getActivity(), view, mProfile.getProfileId());

    mPhotoView = view.findViewById(R.id.profile_photo);

    PostUtils.listenForTimeline(getActivity(), mProfile);
    mPosts = PostUtils.loadTimeline(getActivity());

    mTimeline = view.findViewById(R.id.list_posts);

    setClickListener(view);
    setTextDisplay(view);
    populateProfile(view);

    return view;
}

@Override
public void onResume() {
    super.onResume();

    mPosts = PostUtils.loadTimeline(getActivity());

    mNewsfeedAdapter = new NewsfeedAdapter(getActivity(), mPosts, mAccount);
    mTimeline.setAdapter(mNewsfeedAdapter);
}
John Mack
  • 95
  • 1
  • 7

1 Answers1

0

My constraints were set up incorrectly in the Profile fragment. Updated the XML to the following:

<ListView
    android:id="@+id/list_newsfeed"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/constraintLayout4" />
John Mack
  • 95
  • 1
  • 7