Skip to content

Commit

Permalink
Improved About screen:
Browse files Browse the repository at this point in the history
- Made about 3 pages: plaid, icon, libs
- Added ViewPager indicator
- Fixed cutout text view on M.
- Added, drag dismiss
  • Loading branch information
nickbutcher committed Nov 5, 2015
1 parent fbb1375 commit 21f8c29
Show file tree
Hide file tree
Showing 29 changed files with 1,646 additions and 98 deletions.
14 changes: 7 additions & 7 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
<activity
android:name=".ui.DribbbleShot"
android:parentActivityName=".ui.HomeActivity"
android:theme="@style/Plaid.DribbbleShot">
android:theme="@style/Plaid.Translucent.DribbbleShot">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".ui.HomeActivity" />
Expand All @@ -63,7 +63,7 @@
<activity
android:name=".ui.DesignerNewsStory"
android:parentActivityName=".ui.HomeActivity"
android:theme="@style/Plaid.DesignerNewsStory">
android:theme="@style/Plaid.Translucent.DesignerNewsStory">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".ui.HomeActivity" />
Expand All @@ -72,7 +72,7 @@
<activity
android:name=".ui.SearchActivity"
android:launchMode="singleTop"
android:theme="@style/Plaid.Search">
android:theme="@style/Plaid.Translucent.Search">
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
Expand All @@ -89,7 +89,7 @@
android:name=".ui.DribbbleLogin"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/Plaid.DribbbleLogin">
android:theme="@style/Plaid.Translucent.DribbbleLogin">
<intent-filter>
<data
android:host="dribbble-auth-callback"
Expand All @@ -103,12 +103,12 @@
<activity
android:name=".ui.DesignerNewsLogin"
android:exported="false"
android:theme="@style/Plaid.DesignerNewsLogin"
android:theme="@style/Plaid.Translucent.DesignerNewsLogin"
android:windowSoftInputMode="adjustResize" />

<activity
android:name=".ui.AboutActivity"
android:label="@string/title_activity_about"
android:theme="@style/Plaid.Translucent.About"
android:parentActivityName=".ui.HomeActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
Expand All @@ -118,7 +118,7 @@
<activity
android:name=".ui.PostNewDesignerNewsStory"
android:exported="true"
android:theme="@style/Plaid.PostDesignerNewsStory" />
android:theme="@style/Plaid.Translucent.PostDesignerNewsStory" />

<service
android:name=".data.api.designernews.UpvoteStoryService"
Expand Down
268 changes: 268 additions & 0 deletions app/src/main/java/io/plaidapp/ui/AboutActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,284 @@
package io.plaidapp.ui;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.RecyclerView;
import android.text.Layout;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.AlignmentSpan;
import android.transition.TransitionInflater;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;

import java.security.InvalidParameterException;

import butterknife.Bind;
import butterknife.ButterKnife;
import in.uncod.android.bypass.Bypass;
import io.plaidapp.R;
import io.plaidapp.ui.widget.ElasticDragDismissFrameLayout;
import io.plaidapp.ui.widget.InkPageIndicator;
import io.plaidapp.util.HtmlUtils;
import io.plaidapp.util.glide.CircleTransform;

/**
* About screen. This displays 3 pages in a ViewPager:
* – About Plaid
* – Credit Roman for the awesome icon
* – Credit libraries
*/
public class AboutActivity extends Activity {

@Bind(R.id.draggable_frame) ElasticDragDismissFrameLayout draggableFrame;
@Bind(R.id.pager) ViewPager pager;
@Bind(R.id.indicator) InkPageIndicator pageIndicator;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_about);
ButterKnife.bind(this);

pager.setAdapter(new AboutPagerAdapter(this));
pager.setPageMargin(getResources().getDimensionPixelSize(R.dimen.spacing_normal));
pageIndicator.setViewPager(pager);

draggableFrame.addListener(
new ElasticDragDismissFrameLayout.SystemChromeFader(getWindow()) {
@Override
public void onDragDismissed() {
// if we drag dismiss downward then the default reversal of the enter
// transition would slide content upward which looks weird. So reverse it.
if (draggableFrame.getTranslationY() > 0) {
getWindow().setReturnTransition(
TransitionInflater.from(AboutActivity.this)
.inflateTransition(R.transition.about_return_downward));
}
finishAfterTransition();
}
});
}

static class AboutPagerAdapter extends PagerAdapter {

private View aboutPlaid;
@Nullable @Bind(R.id.about_description) TextView plaidDescription;
private View aboutIcon;
@Nullable @Bind(R.id.icon_description) TextView iconDescription;
private View aboutLibs;
@Nullable @Bind(R.id.libs_list) RecyclerView libsList;

private final LayoutInflater layoutInflater;
private final Bypass markdown;

public AboutPagerAdapter(Context context) {
layoutInflater = LayoutInflater.from(context);
markdown = new Bypass(context, new Bypass.Options());
}

@Override
public Object instantiateItem(ViewGroup collection, int position) {
View layout = getPage(position, collection);
collection.addView(layout);
return layout;
}

@Override
public void destroyItem(ViewGroup collection, int position, Object view) {
collection.removeView((View) view);
}

@Override
public int getCount() {
return 3;
}

@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}

private View getPage(int position, ViewGroup parent) {
switch (position) {
case 0:
if (aboutPlaid == null) {
aboutPlaid = layoutInflater.inflate(R.layout.about_plaid, parent, false);
ButterKnife.bind(this, aboutPlaid);
// fun with spans & markdown
CharSequence about0 = markdown.markdownToSpannable(parent.getResources()
.getString(R.string.about_plaid_0), plaidDescription, null);
SpannableString about1 = new SpannableString(
parent.getResources().getString(R.string.about_plaid_1));
about1.setSpan(new AlignmentSpan.Standard(Layout.Alignment.ALIGN_CENTER),
0, about1.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
SpannableString about2 = new SpannableString(markdown.markdownToSpannable
(parent.getResources().getString(R.string.about_plaid_2),
plaidDescription, null));
about2.setSpan(new AlignmentSpan.Standard(Layout.Alignment.ALIGN_CENTER),
0, about2.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
SpannableString about3 = new SpannableString(markdown.markdownToSpannable
(parent.getResources().getString(R.string.about_plaid_3),
plaidDescription, null));
about3.setSpan(new AlignmentSpan.Standard(Layout.Alignment.ALIGN_CENTER),
0, about3.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
CharSequence desc = TextUtils.concat(about0, "\n\n", about1, "\n", about2,
"\n\n", about3);
HtmlUtils.setTextWithNiceLinks(plaidDescription, desc);
}
return aboutPlaid;
case 1:
if (aboutIcon == null) {
aboutIcon = layoutInflater.inflate(R.layout.about_icon, parent, false);
ButterKnife.bind(this, aboutIcon);
CharSequence icon0 = parent.getResources().getString(R.string.about_icon_0);
CharSequence icon1 = markdown.markdownToSpannable(parent.getResources()
.getString(R.string.about_icon_1), iconDescription, null);
CharSequence iconDesc = TextUtils.concat(icon0, "\n", icon1);
HtmlUtils.setTextWithNiceLinks(iconDescription, iconDesc);
}
return aboutIcon;
case 2:
if (aboutLibs == null) {
aboutLibs = layoutInflater.inflate(R.layout.about_libs, parent, false);
ButterKnife.bind(this, aboutLibs);
libsList.setAdapter(new LibraryAdapter(parent.getContext()));
}
return aboutLibs;
}
throw new InvalidParameterException();
}
}

private static class LibraryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

private static final int VIEW_TYPE_INTRO = 0;
private static final int VIEW_TYPE_LIBRARY = 1;
private static final Library[] libs = {
new Library("Android support libs",
"https://android.googlesource.com/platform/frameworks/support/",
"http://developer.android.com/assets/images/[email protected]"),
new Library("ButterKnife",
"http://jakewharton.github.io/butterknife/",
"https://avatars.githubusercontent.com/u/66577"),
new Library("Bypass",
"https://github.com/Uncodin/bypass",
"https://avatars.githubusercontent.com/u/1072254"),
new Library("Glide",
"https://github.com/bumptech/glide",
"https://avatars.githubusercontent.com/u/423539"),
new Library("JSoup",
"https://github.com/jhy/jsoup/",
"https://avatars.githubusercontent.com/u/76934"),
new Library("OkHttp",
"http://square.github.io/okhttp/",
"https://avatars.githubusercontent.com/u/82592"),
new Library("Retrofit",
"http://square.github.io/retrofit/",
"https://avatars.githubusercontent.com/u/82592") };

private final CircleTransform circleCrop;

public LibraryAdapter(Context context) {
circleCrop = new CircleTransform(context);
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case VIEW_TYPE_INTRO:
return new LibraryIntroHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.about_lib_intro, parent, false));
case VIEW_TYPE_LIBRARY:
return new LibraryHolder(LayoutInflater.from(parent.getContext()).inflate(
R.layout.library, parent, false));
}
throw new InvalidParameterException();
}

@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
if (getItemViewType(position) == VIEW_TYPE_LIBRARY) {
bindLibrary((LibraryHolder) holder, libs[position - 1]); // adjust for intro
}
}

@Override
public int getItemViewType(int position) {
return position == 0 ? VIEW_TYPE_INTRO : VIEW_TYPE_LIBRARY;
}

@Override
public int getItemCount() {
return libs.length + 1; // + 1 for the static intro view
}

private void bindLibrary(final LibraryHolder holder, final Library lib) {
holder.name.setText(lib.name);
Glide.with(holder.image.getContext())
.load(lib.imageUrl)
.transform(circleCrop)
.into(holder.image);
final View.OnClickListener clickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
holder.link.getContext().startActivity(
new Intent(Intent.ACTION_VIEW, Uri.parse(lib.link)));
}
};
holder.itemView.setOnClickListener(clickListener);
holder.link.setOnClickListener(clickListener);
}
}

static class LibraryHolder extends RecyclerView.ViewHolder {

@Bind(R.id.library_image) ImageView image;
@Bind(R.id.library_name) TextView name;
@Bind(R.id.library_link) Button link;

public LibraryHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}

static class LibraryIntroHolder extends RecyclerView.ViewHolder {

TextView intro;

public LibraryIntroHolder(View itemView) {
super(itemView);
intro = (TextView) itemView;
}
}

/**
* Models an open source library we want to credit
*/
private static class Library {
public final String name;
public final String link;
public final String imageUrl;

public Library(String name, String link, String imageUrl) {
this.name = name;
this.link = link;
this.imageUrl = imageUrl;
}
}

}
3 changes: 2 additions & 1 deletion app/src/main/java/io/plaidapp/ui/HomeActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,8 @@ public boolean onOptionsItemSelected(MenuItem item) {
}
return true;
case R.id.menu_about:
startActivity(new Intent(HomeActivity.this, AboutActivity.class));
startActivity(new Intent(HomeActivity.this, AboutActivity.class),
ActivityOptions.makeSceneTransitionAnimation(this).toBundle());
return true;
}
return super.onOptionsItemSelected(item);
Expand Down
Loading

0 comments on commit 21f8c29

Please sign in to comment.