Display a custom error view when there is something wrong when loading best posts. Probably fix a bug that holder.getAdapterPosition() returns -1 when loading subreddit icons in the RecyclerView of PostFragment. Subreddit banners are parsed correctly in ParseSubscribedThing. Check if the api call is successful in onResponse. Rewrite some methods.

This commit is contained in:
Alex Ning 2018-08-30 14:08:02 +08:00
parent 3fa6257428
commit 4364e20e36
12 changed files with 172 additions and 110 deletions

View File

@ -27,7 +27,12 @@ class FetchComment {
comments.enqueue(new Callback<String>() {
@Override
public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) {
fetchCommentListener.onFetchCommentSuccess(response.body());
if(response.isSuccessful()) {
fetchCommentListener.onFetchCommentSuccess(response.body());
} else {
Log.i("call failed", response.message());
fetchCommentListener.onFetchCommentFail();
}
}
@Override

View File

@ -27,7 +27,12 @@ class FetchSubredditData {
subredditData.enqueue(new Callback<String>() {
@Override
public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) {
fetchSubredditDataListener.onFetchSubredditDataSuccess(response.body());
if(response.isSuccessful()) {
fetchSubredditDataListener.onFetchSubredditDataSuccess(response.body());
} else {
Log.i("call failed", response.message());
fetchSubredditDataListener.onFetchSubredditDataFail();
}
}
@Override

View File

@ -44,45 +44,52 @@ class FetchSubscribedThing {
subredditDataCall.enqueue(new Callback<String>() {
@Override
public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) {
ParseSubscribedThing.parseSubscribedSubreddits(response.body(), subscribedSubredditData,
subscribedUserData, subredditData,
new ParseSubscribedThing.ParseSubscribedSubredditsListener() {
if(response.isSuccessful()) {
ParseSubscribedThing.parseSubscribedSubreddits(response.body(), subscribedSubredditData,
subscribedUserData, subredditData,
new ParseSubscribedThing.ParseSubscribedSubredditsListener() {
@Override
public void onParseSubscribedSubredditsSuccess(ArrayList<SubscribedSubredditData> subscribedSubredditData,
ArrayList<SubscribedUserData> subscribedUserData,
ArrayList<SubredditData> subredditData,
String lastItem) {
if(lastItem.equals("null")) {
fetchSubscribedThingListener.onFetchSubscribedThingSuccess(
subscribedSubredditData, subscribedUserData, subredditData);
} else {
fetchSubscribedThing(context, lastItem, subscribedSubredditData,
subscribedUserData, subredditData,
fetchSubscribedThingListener, refreshTime);
@Override
public void onParseSubscribedSubredditsSuccess(ArrayList<SubscribedSubredditData> subscribedSubredditData,
ArrayList<SubscribedUserData> subscribedUserData,
ArrayList<SubredditData> subredditData,
String lastItem) {
if(lastItem.equals("null")) {
fetchSubscribedThingListener.onFetchSubscribedThingSuccess(
subscribedSubredditData, subscribedUserData, subredditData);
} else {
fetchSubscribedThing(context, lastItem, subscribedSubredditData,
subscribedUserData, subredditData,
fetchSubscribedThingListener, refreshTime);
}
}
}
@Override
public void onParseSubscribedSubredditsFail() {
fetchSubscribedThingListener.onFetchSubscribedThingFail();
}
});
@Override
public void onParseSubscribedSubredditsFail() {
fetchSubscribedThingListener.onFetchSubscribedThingFail();
}
});
} else if(response.code() == 401) {
RefreshAccessToken.refreshAccessToken(context, new RefreshAccessToken.RefreshAccessTokenListener() {
@Override
public void onRefreshAccessTokenSuccess() {
fetchSubscribedThing(context, lastItem, subscribedSubredditData,
subscribedUserData, subredditData, fetchSubscribedThingListener, refreshTime - 1);
}
@Override
public void onRefreshAccessTokenFail() {}
});
} else {
Log.i("call failed", response.message());
fetchSubscribedThingListener.onFetchSubscribedThingFail();
}
}
@Override
public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) {
Log.i("call failed", t.getMessage());
RefreshAccessToken.refreshAccessToken(context, new RefreshAccessToken.RefreshAccessTokenListener() {
@Override
public void onRefreshAccessTokenSuccess() {
fetchSubscribedThing(context, lastItem, subscribedSubredditData,
subscribedUserData, subredditData, fetchSubscribedThingListener, refreshTime);
}
@Override
public void onRefreshAccessTokenFail() {}
});
fetchSubscribedThingListener.onFetchSubscribedThingFail();
}
});
}

View File

@ -34,21 +34,28 @@ class FetchUserInfo {
userInfo.enqueue(new Callback<String>() {
@Override
public void onResponse(@NonNull Call<String> call, @NonNull retrofit2.Response<String> response) {
fetchUserInfoListener.onFetchUserInfoSuccess(response.body());
if(response.isSuccessful()) {
fetchUserInfoListener.onFetchUserInfoSuccess(response.body());
} else if(response.code() == 401){
RefreshAccessToken.refreshAccessToken(context, new RefreshAccessToken.RefreshAccessTokenListener() {
@Override
public void onRefreshAccessTokenSuccess() {
fetchUserInfo(context, fetchUserInfoListener, refreshTime - 1);
}
@Override
public void onRefreshAccessTokenFail() {}
});
} else {
Log.i("call failed", response.message());
fetchUserInfoListener.onFetchUserInfoFail();
}
}
@Override
public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) {
Log.i("call failed", t.getMessage());
RefreshAccessToken.refreshAccessToken(context, new RefreshAccessToken.RefreshAccessTokenListener() {
@Override
public void onRefreshAccessTokenSuccess() {
fetchUserInfo(context, fetchUserInfoListener, refreshTime - 1);
}
@Override
public void onRefreshAccessTokenFail() {}
});
fetchUserInfoListener.onFetchUserInfoFail();
}
});
}

View File

@ -65,7 +65,7 @@ class ParseSubscribedThing {
for(int i = 0; i < children.length(); i++) {
JSONObject data = children.getJSONObject(i).getJSONObject(JSONUtils.DATA_KEY);
String name = data.getString(JSONUtils.DISPLAY_NAME);
String bannerImageUrl = data.getString(JSONUtils.BANNER_IMG_KEY);
String bannerImageUrl = data.getString(JSONUtils.BANNER_BACKGROUND_IMAGE_KEY);
if(bannerImageUrl.equals("") || bannerImageUrl.equals("null")) {
bannerImageUrl= data.getString(JSONUtils.BANNER_IMG_KEY);
if(bannerImageUrl.equals("null")) {

View File

@ -16,8 +16,11 @@ import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
@ -43,6 +46,8 @@ public class PostFragment extends Fragment {
private String mLastItem;
private PaginationSynchronizer mPaginationSynchronizer;
private PostRecyclerViewAdapter mAdapter;
private LinearLayout mFetchPostErrorLinearLayout;
private ImageView mFetchPostErrorImageView;
private boolean mIsBestPost;
private String mSubredditName;
@ -73,7 +78,7 @@ public class PostFragment extends Fragment {
if(mIsBestPost) {
fetchBestPost(1);
} else {
fetchPost(mSubredditName, 1);
fetchPost();
}
}
}
@ -108,6 +113,8 @@ public class PostFragment extends Fragment {
mLinearLayoutManager = new LinearLayoutManager(getActivity());
mPostRecyclerView.setLayoutManager(mLinearLayoutManager);
mProgressBar = rootView.findViewById(R.id.progress_bar_post_fragment);
mFetchPostErrorLinearLayout = rootView.findViewById(R.id.fetch_post_error_linear_layout_post_fragment);
mFetchPostErrorImageView = rootView.findViewById(R.id.fetch_post_error_image_view_post_fragment);
/*FloatingActionButton fab = rootView.findViewById(R.id.fab_post_fragment);
fab.setOnClickListener(new View.OnClickListener() {
@Override
@ -120,6 +127,17 @@ public class PostFragment extends Fragment {
mIsBestPost = getArguments().getBoolean(IS_BEST_POST_KEY);
if(!mIsBestPost) {
mSubredditName = getArguments().getString(SUBREDDIT_NAME_KEY);
} else {
mFetchPostErrorLinearLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(mIsBestPost) {
fetchBestPost(1);
} else {
fetchPost();
}
}
});
}
if(savedInstanceState != null && savedInstanceState.getParcelable(paginationSynchronizerState) != null) {
@ -129,7 +147,7 @@ public class PostFragment extends Fragment {
if(mIsBestPost) {
fetchBestPost(1);
} else {
fetchPost(mSubredditName, 1);
fetchPost();
}
}
@ -146,10 +164,11 @@ public class PostFragment extends Fragment {
private void fetchBestPost(final int refreshTime) {
if(refreshTime < 0) {
showErrorSnackbar();
showErrorView();
return;
}
mFetchPostErrorLinearLayout.setVisibility(View.GONE);
mProgressBar.setVisibility(View.VISIBLE);
Retrofit retrofit = new Retrofit.Builder()
@ -166,7 +185,6 @@ public class PostFragment extends Fragment {
@Override
public void onResponse(Call<String> call, retrofit2.Response<String> response) {
if(getActivity() != null) {
if(response.isSuccessful()) {
ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("response", response.body());
@ -191,9 +209,8 @@ public class PostFragment extends Fragment {
@Override
public void onParsePostFail() {
Toast.makeText(getActivity(), "Error parsing data", Toast.LENGTH_SHORT).show();
Log.i("Post fetch error", "Error parsing data");
mProgressBar.setVisibility(View.GONE);
showErrorView();
}
});
} else if(response.code() == 401) {
@ -211,24 +228,20 @@ public class PostFragment extends Fragment {
});
} else {
Log.i("Post fetch error", response.message());
showErrorSnackbar();
showErrorView();
}
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
showErrorSnackbar();
showErrorView();
}
});
}
private void fetchPost(final String queryPostUrl, final int refreshTime) {
if(refreshTime < 0) {
showErrorSnackbar();
return;
}
private void fetchPost() {
mFetchPostErrorLinearLayout.setVisibility(View.GONE);
mProgressBar.setVisibility(View.VISIBLE);
Retrofit retrofit = new Retrofit.Builder()
@ -242,7 +255,6 @@ public class PostFragment extends Fragment {
@Override
public void onResponse(Call<String> call, retrofit2.Response<String> response) {
if(getActivity() != null) {
Log.i("response_code", Integer.toString(response.code()));
if(response.isSuccessful()) {
ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("response", response.body());
@ -267,38 +279,42 @@ public class PostFragment extends Fragment {
@Override
public void onParsePostFail() {
Toast.makeText(getActivity(), "Error parsing data", Toast.LENGTH_SHORT).show();
Log.i("Post fetch error", "Error parsing data");
mProgressBar.setVisibility(View.GONE);
showErrorView();
}
});
} else {
Log.i("Post fetch error", response.message());
showErrorSnackbar();
showErrorView();
}
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
showErrorSnackbar();
showErrorView();
}
});
}
private void showErrorSnackbar() {
private void showErrorView() {
mProgressBar.setVisibility(View.GONE);
Snackbar snackbar = Snackbar.make(mCoordinatorLayout, "Error getting post", Snackbar.LENGTH_INDEFINITE);
snackbar.setAction(R.string.retry, new View.OnClickListener() {
@Override
public void onClick(View view) {
if(mIsBestPost) {
fetchBestPost(1);
} else {
fetchPost(mSubredditName, 1);
if(mIsBestPost) {
mFetchPostErrorLinearLayout.setVisibility(View.VISIBLE);
Glide.with(this).load(R.drawable.load_post_error_indicator).into(mFetchPostErrorImageView);
} else {
Snackbar snackbar = Snackbar.make(mCoordinatorLayout, "Error getting post", Snackbar.LENGTH_INDEFINITE);
snackbar.setAction(R.string.retry, new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mIsBestPost) {
fetchBestPost(1);
} else {
fetchPost();
}
}
}
});
snackbar.show();
});
snackbar.show();
}
}
}

View File

@ -80,21 +80,22 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
}
@Override
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, int position) {
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, final int position) {
if(holder instanceof DataViewHolder) {
if(mPostData.get(position) == null) {
Log.i("is null", Integer.toString(position));
} else {
final String id = mPostData.get(holder.getAdapterPosition()).getFullName();
final String subredditName = mPostData.get(holder.getAdapterPosition()).getSubredditNamePrefixed();
final String postTime = mPostData.get(holder.getAdapterPosition()).getPostTime();
final String title = mPostData.get(holder.getAdapterPosition()).getTitle();
final String permalink = mPostData.get(holder.getAdapterPosition()).getPermalink();
int voteType = mPostData.get(holder.getAdapterPosition()).getVoteType();
int gilded = mPostData.get(holder.getAdapterPosition()).getGilded();
boolean nsfw = mPostData.get(holder.getAdapterPosition()).isNSFW();
final int adapterPosition = holder.getAdapterPosition();
final String id = mPostData.get(adapterPosition).getFullName();
final String subredditName = mPostData.get(adapterPosition).getSubredditNamePrefixed();
final String postTime = mPostData.get(adapterPosition).getPostTime();
final String title = mPostData.get(adapterPosition).getTitle();
final String permalink = mPostData.get(adapterPosition).getPermalink();
int voteType = mPostData.get(adapterPosition).getVoteType();
int gilded = mPostData.get(adapterPosition).getGilded();
boolean nsfw = mPostData.get(adapterPosition).isNSFW();
if(mPostData.get(holder.getAdapterPosition()).getSubredditIconUrl() == null) {
if(mPostData.get(adapterPosition).getSubredditIconUrl() == null) {
new LoadSubredditIconAsyncTask(subredditDao, subredditName,
new LoadSubredditIconAsyncTask.LoadSubredditIconAsyncTaskListener() {
@Override
@ -107,7 +108,7 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
.into(((DataViewHolder) holder).subredditIconCircleImageView);
}
mPostData.get(holder.getAdapterPosition()).setSubredditIconUrl(iconImageUrl);
mPostData.get(adapterPosition).setSubredditIconUrl(iconImageUrl);
}
}).execute();
} else if(!mPostData.get(position).getSubredditIconUrl().equals("")) {
@ -123,7 +124,7 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
canStartActivity = false;
Intent intent = new Intent(mContext, ViewPostDetailActivity.class);
intent.putExtra(ViewPostDetailActivity.EXTRA_TITLE, title);
intent.putExtra(ViewPostDetailActivity.EXTRA_POST_DATA, mPostData.get(holder.getAdapterPosition()));
intent.putExtra(ViewPostDetailActivity.EXTRA_POST_DATA, mPostData.get(adapterPosition));
mContext.startActivity(intent);
}
}
@ -134,7 +135,7 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
public void onClick(View view) {
Intent intent = new Intent(mContext, ViewSubredditDetailActivity.class);
intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY,
mPostData.get(holder.getAdapterPosition()).getSubredditNamePrefixed().substring(2));
mPostData.get(adapterPosition).getSubredditNamePrefixed().substring(2));
}
});
@ -259,10 +260,10 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
Intent intent = new Intent(mContext, ViewVideoActivity.class);
intent.setData(gifVideoUri);
intent.putExtra(ViewVideoActivity.TITLE_KEY, title);
intent.putExtra(ViewVideoActivity.IS_DASH_VIDEO_KEY, mPostData.get(holder.getAdapterPosition()).isDashVideo());
intent.putExtra(ViewVideoActivity.IS_DOWNLOADABLE_KEY, mPostData.get(holder.getAdapterPosition()).isDownloadableGifOrVideo());
if(mPostData.get(holder.getAdapterPosition()).isDownloadableGifOrVideo()) {
intent.putExtra(ViewVideoActivity.DOWNLOAD_URL_KEY, mPostData.get(holder.getAdapterPosition()).getGifOrVideoDownloadUrl());
intent.putExtra(ViewVideoActivity.IS_DASH_VIDEO_KEY, mPostData.get(adapterPosition).isDashVideo());
intent.putExtra(ViewVideoActivity.IS_DOWNLOADABLE_KEY, mPostData.get(adapterPosition).isDownloadableGifOrVideo());
if(mPostData.get(adapterPosition).isDownloadableGifOrVideo()) {
intent.putExtra(ViewVideoActivity.DOWNLOAD_URL_KEY, mPostData.get(adapterPosition).getGifOrVideoDownloadUrl());
intent.putExtra(ViewVideoActivity.SUBREDDIT_KEY, subredditName);
intent.putExtra(ViewVideoActivity.ID_KEY, id);
}
@ -295,10 +296,10 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
Intent intent = new Intent(mContext, ViewVideoActivity.class);
intent.setData(videoUri);
intent.putExtra(ViewVideoActivity.TITLE_KEY, title);
intent.putExtra(ViewVideoActivity.IS_DASH_VIDEO_KEY, mPostData.get(holder.getAdapterPosition()).isDashVideo());
intent.putExtra(ViewVideoActivity.IS_DOWNLOADABLE_KEY, mPostData.get(holder.getAdapterPosition()).isDownloadableGifOrVideo());
if(mPostData.get(holder.getAdapterPosition()).isDownloadableGifOrVideo()) {
intent.putExtra(ViewVideoActivity.DOWNLOAD_URL_KEY, mPostData.get(holder.getAdapterPosition()).getGifOrVideoDownloadUrl());
intent.putExtra(ViewVideoActivity.IS_DASH_VIDEO_KEY, mPostData.get(adapterPosition).isDashVideo());
intent.putExtra(ViewVideoActivity.IS_DOWNLOADABLE_KEY, mPostData.get(adapterPosition).isDownloadableGifOrVideo());
if(mPostData.get(adapterPosition).isDownloadableGifOrVideo()) {
intent.putExtra(ViewVideoActivity.DOWNLOAD_URL_KEY, mPostData.get(adapterPosition).getGifOrVideoDownloadUrl());
intent.putExtra(ViewVideoActivity.SUBREDDIT_KEY, subredditName);
intent.putExtra(ViewVideoActivity.ID_KEY, id);
}
@ -337,9 +338,9 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
if (((DataViewHolder) holder).upvoteButton.getColorFilter() == null) {
((DataViewHolder) holder).upvoteButton.setColorFilter(ContextCompat.getColor(mContext, R.color.colorPrimary), android.graphics.PorterDuff.Mode.SRC_IN);
if(isDownvotedBefore) {
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(holder.getAdapterPosition()).getScore() + 2));
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(adapterPosition).getScore() + 2));
} else {
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(holder.getAdapterPosition()).getScore() + 1));
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(adapterPosition).getScore() + 1));
}
VoteThing.voteThing(mContext, new VoteThing.VoteThingListener() {
@ -364,7 +365,7 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
} else {
//Upvoted before
((DataViewHolder) holder).upvoteButton.clearColorFilter();
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(holder.getAdapterPosition()).getScore() - 1));
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(adapterPosition).getScore() - 1));
VoteThing.voteThing(mContext, new VoteThing.VoteThingListener() {
@Override
@ -395,9 +396,9 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
if (((DataViewHolder) holder).downvoteButton.getColorFilter() == null) {
((DataViewHolder) holder).downvoteButton.setColorFilter(ContextCompat.getColor(mContext, R.color.minusButtonColor), android.graphics.PorterDuff.Mode.SRC_IN);
if (isUpvotedBefore) {
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(holder.getAdapterPosition()).getScore() - 2));
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(adapterPosition).getScore() - 2));
} else {
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(holder.getAdapterPosition()).getScore() - 1));
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(adapterPosition).getScore() - 1));
}
VoteThing.voteThing(mContext, new VoteThing.VoteThingListener() {
@ -418,11 +419,11 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(position).getScore()));
((DataViewHolder) holder).upvoteButton.setColorFilter(upvoteButtonColorFilter);
}
}, id, RedditUtils.DIR_DOWNVOTE, holder.getAdapterPosition(), 1);
}, id, RedditUtils.DIR_DOWNVOTE, adapterPosition, 1);
} else {
//Down voted before
((DataViewHolder) holder).downvoteButton.clearColorFilter();
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(holder.getAdapterPosition()).getScore() + 1));
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(adapterPosition).getScore() + 1));
VoteThing.voteThing(mContext, new VoteThing.VoteThingListener() {
@Override
@ -438,7 +439,7 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(position).getScore()));
mPostData.get(position).setScore(mPostData.get(position).getScore());
}
}, id, RedditUtils.DIR_UNVOTE, holder.getAdapterPosition(), 1);
}, id, RedditUtils.DIR_UNVOTE, adapterPosition, 1);
}
}
});

View File

@ -60,8 +60,4 @@ class RedditUtils {
params.put(RedditUtils.USER_AGENT_KEY, RedditUtils.USER_AGENT);
return params;
}
static String getQuerySubredditPostUrl(String subredditName) {
return API_BASE_URI + "/r/" + subredditName + ".json";
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

View File

@ -21,7 +21,7 @@
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
app:toolbarId="@+id/toolbar">
<RelativeLayout
@ -109,6 +109,7 @@
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
app:popupTheme="@style/AppTheme.PopupOverlay"
app:navigationIcon="?attr/homeAsUpIndicator" />

View File

@ -19,6 +19,28 @@
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="@+id/fetch_post_error_linear_layout_post_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<ImageView
android:id="@+id/fetch_post_error_image_view_post_fragment"
android:layout_width="150dp"
android:layout_height="wrap_content" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center"
android:text="@string/load_posts_error"/>
</LinearLayout>
<!--<android.support.design.widget.FloatingActionButton
android:id="@+id/fab_post_fragment"
android:layout_width="wrap_content"

View File

@ -8,6 +8,8 @@
<string name="action_settings">Settings</string>
<string name="action_download">Download</string>
<string name="load_posts_error">Error loading posts.\nTap to retry.</string>
<string name="load_data_failed">Cannot load posts</string>
<string name="load_comment_failed">Error loading comments</string>
<string name="retry">Retry</string>