diff --git a/README.md b/README.md index 3198a2c..0ac0b25 100644 --- a/README.md +++ b/README.md @@ -15,21 +15,13 @@ For demonstration and experimentation, an apk of the sample project can be downl ## Usage The Gradle dependency is available through jCenter, which is used by default in Android Studio. To add the dependency to your project, copy this line into the dependencies section of your app's build.gradle file. - -##### AndroidX -The Android support libraries are being refactored from `android.support.*` to `androidx.*` as detailed [here](https://developer.android.com/topic/libraries/support-library/androidx-overview). Until the refactored libraries reach version `1.0.0` (as of the time of writing the latest verison is `1.0.0-rc02`), two versions of Attribouter will be released - one for AndroidX, and one for old support libraries. - ```gradle -implementation 'me.jfenn:attribouter:0.1.3' -``` - -##### Old Support Libraries - -```gradle -implementation 'me.jfenn:attribouter:0.1.2' +implementation 'me.jfenn:attribouter:0.1.4' ``` +##### Support Libraries +The Android support libraries have been refactored from `android.support.*` to `androidx.*` as detailed [here](https://developer.android.com/topic/libraries/support-library/androidx-overview). As such, Attribouter only uses the new dependencies. If your project still uses the older support libraries for some reason, you may either compile your own version of Attribouter or use the last version to use the old support libraries, `0.1.2`. ### Starting an Activity This is pretty simple. diff --git a/app/build.gradle b/app/build.gradle index 83f0256..1839859 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -24,8 +24,8 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'androidx.appcompat:appcompat:1.0.0-rc02' - implementation 'com.google.android.material:material:1.0.0-rc02' + implementation 'androidx.appcompat:appcompat:1.0.0' + implementation 'com.google.android.material:material:1.0.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test:runner:1.1.0-alpha4' androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-alpha4' diff --git a/attribouter/build.gradle b/attribouter/build.gradle index 443ef77..d035acc 100644 --- a/attribouter/build.gradle +++ b/attribouter/build.gradle @@ -3,7 +3,7 @@ apply plugin: 'com.android.library' ext { PUBLISH_GROUP_ID = 'me.jfenn' PUBLISH_ARTIFACT_ID = 'attribouter' - PUBLISH_VERSION = '0.1.3' + PUBLISH_VERSION = '0.1.4' } android { @@ -12,8 +12,8 @@ android { defaultConfig { minSdkVersion 15 targetSdkVersion 28 - versionCode 12 - versionName "0.1.3" + versionCode 13 + versionName "0.1.4" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true @@ -30,9 +30,9 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'androidx.appcompat:appcompat:1.0.0-rc02' - implementation 'androidx.browser:browser:1.0.0-rc02' - implementation 'com.google.android.material:material:1.0.0-rc02' + implementation 'androidx.appcompat:appcompat:1.0.0' + implementation 'androidx.browser:browser:1.0.0' + implementation 'com.google.android.material:material:1.0.0' implementation 'com.google.code.gson:gson:2.8.4' implementation 'com.google.android:flexbox:1.0.0' implementation 'com.github.bumptech.glide:glide:4.7.1' diff --git a/attribouter/src/main/java/me/jfenn/attribouter/wedges/link/LinkWedge.java b/attribouter/src/main/java/me/jfenn/attribouter/wedges/link/LinkWedge.java index b9f9d06..f7d7c86 100644 --- a/attribouter/src/main/java/me/jfenn/attribouter/wedges/link/LinkWedge.java +++ b/attribouter/src/main/java/me/jfenn/attribouter/wedges/link/LinkWedge.java @@ -3,6 +3,7 @@ import android.content.Context; import android.content.res.XmlResourceParser; import android.view.View; +import android.webkit.URLUtil; import android.widget.ImageView; import android.widget.TextView; @@ -44,7 +45,8 @@ public LinkWedge(@Nullable String id, @Nullable String name, @Nullable String ur super(R.layout.item_attribouter_link); this.id = id; this.name = name; - this.url = url; + if (url != null && url.length() > 0) + this.url = url.startsWith("http") ? url : "http://" + url; this.icon = icon; this.isHidden = isHidden; this.priority = priority; @@ -69,7 +71,7 @@ public String getName(Context context) { */ @Nullable public View.OnClickListener getListener(Context context) { - if (url != null && url.length() > 0) + if (url != null && url.length() > 0 && URLUtil.isValidUrl(url)) return new UrlClickListener(ResourceUtils.getString(context, url)); else return null; } diff --git a/docs/README.md b/docs/README.md index 9c284d8..c239b61 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,26 +2,26 @@ Welcome to Attribouter's in-depth documentation page! It provides several exampl ## Tutorials -- [The Configuration File](./CONFIGURATION.md) -- [Overriding Resources and Providing Translations](./RESOURCES.md) -- [Extending A Wedge](./SUBWEDGING.md) -- [Custom Themes](./THEMING.md) +- [The Configuration File](./configuration.md) +- [Overriding Resources and Providing Translations](./resources.md) +- [Extending A Wedge](./subwedging.md) +- [Custom Themes](./theming.md) ## Docs -- [AppWedge](./wedges/APP.md) -- [ContributorsWedge](./wedges/CONTRIBUTORS.md) - - [ContributorWedge](./wedges/CONTRIBUTOR.md) -- [LicensesWedge](./wedges/LICENSES.md) - - [LicenseWedge](./wedges/LICENSE.md) -- [TranslatorsWedge](./wedges/TRANSLATORS.md) - - [TranslatorWedge](./wedges/TRANSLATOR.md) -- [TextWedge](./wedges/TEXT.md) -- [LinkWedge](./wedges/LINK.md) - - [EmailLinkWedge](./wedges/LINK.md#email) - - [LicenseLinkWedge](./wedges/LINK.md#license) - - [PlayStoreLinkWedge](./wedges/LINK.md#play-store) +- [AppWedge](./wedges/app.md) +- [ContributorsWedge](./wedges/contributors.md) + - [ContributorWedge](./wedges/contributor.md) +- [LicensesWedge](./wedges/licenses.md) + - [LicenseWedge](./wedges/license.md) +- [TranslatorsWedge](./wedges/translators.md) + - [TranslatorWedge](./wedges/translator.md) +- [TextWedge](./wedges/text.md) +- [LinkWedge](./wedges/link.md) + - [EmailLinkWedge](./wedges/link.md#email) + - [LicenseLinkWedge](./wedges/link.md#license) + - [PlayStoreLinkWedge](./wedges/link.md#play-store) ## Automation -- [Fetching CrowdIn Translations](./utils/CROWDIN.md) by [@deletescape](https://github.com/deletescape) +- [Fetching CrowdIn Translations](./utils/crowdin.md) by [@deletescape](https://github.com/deletescape) diff --git a/docs/CONFIGURATION.md b/docs/configuration.md similarity index 91% rename from docs/CONFIGURATION.md rename to docs/configuration.md index 986a861..75ec1c5 100644 --- a/docs/CONFIGURATION.md +++ b/docs/configuration.md @@ -1,136 +1,136 @@ ---- -title: The Configuration File ---- - -# The Configuration File - -The great File of Configuration is truly a mighty hurdle to overcome when implementing this library. It contains many confusing and difficult concepts such as "tags" and "attributes". However, when it comes down to it, it is really just a weird form of layout file that specifies the information to display instead of how to display it. - -For no specific reason, each configuration file must have an `` tag as its root element. Inside of that tag, any amount of children can be defined in any order. When the about screen is opened, these tags will be parsed and their corresponding objects will be created, much like inflating a layout file. The objects are then added to a list to be displayed in a RecyclerView. In order to simplify things, these tags, their corresponding objects, and the views created for them in the RecyclerView will be referred to as "wedges". - -Because wedge classes are instantiated from the configruation file, the wedge's tag in the file must be the class name of the wedge that should be instantiated, including the package name. This is the same as adding a custom view to a layout file. - -With this information, we can now create a simple configuration file using the [`App`](./wedges/APP.md), [`Contributors`](./wedges/CONTRIBUTORS.md), and [`Licenses`](./wedges/LICENSES.md) wedges as follows. - -```xml - - - - - - - - - -``` - -This will create a screen that displays information about your app, followed by its contributors and finally the open source licenses that you have used. However, the only information that is currently displayed is what Attribouter knows how to find by itself; the `AppWedge` displays your app's icon, name, and a link to rate your app on the Play Store, the `ContributorsWedge` displays the people that have contributed to Attribouter, and the `LicensesWedge` displays the licenses that Attribouter uses. In order to add information to these wedges, you can use one of the following options: - -## Option 1: The GitHub API - -As stated in their documentation, both the [`AppWedge`](./wedges/APP.md) and the [`ContributorsWedge`](./wedges/CONTRIBUTORS.md) have an attribute titled `repo` that accepts the full name of a GitHub repository. Let's say that the repository for your app is [TheAndroidMaster/Pasta-for-Spotify](https://jfenn.me/redirects/?t=github&d=Pasta-for-Spotify). In that case, you can modify the file as follows: - -```xml - - - - - - - - - -``` - -The `AppWedge` now displays the repository's description, a link to the Pasta-for-Spotify repository on GitHub, and a link to the project's homepage ([https://jfenn.me/apps/pasta](https://jfenn.me/apps/pasta/)), and the `ContributorsWedge` includes all of [the people that have contributed to it](https://jfenn.me/redirects/?t=github&d=Pasta-for-Spotify/graphs/contributors). - -## Option 2: Attributes and Children - -If your project does not have a GitHub repository or you want some information to be available without an internet connection, you should define that information in the configuration file. Using the documentation pages for `AppWedge` and `ContributorsWedge`, the equivalent of Option 1 (without the GitHub link in the `AppWedge`) would be as follows: - -```xml - - - - - - - - - - - - - - - - - -``` - -## Option 3: Both - -> "This should be fairly easy. All that you need to do is combine the two previous options, right?" - -Actually, there is one extra step - if you do not define the `login` attribute on all of the [`ContributorWedge`](./wedges/CONTRIBUTOR.md)s, you will end up with two sets of contributors - one from the configuration file and one from the GitHub API. Similar attributes are used to merge duplicate wedges like [`LinkWedge`](./wedges/LINK.md)s and [`LicenseWedge`](./wedges/LICENSE.md)s, so you should check out ["Overriding Resources and Providing Translations"](../RESOURCES.md) if the results of this option confuse you. When you are done, the end result should look something like this: - -```xml - - - - - - - - - - - - - - - - - -``` +--- +title: The Configuration File +--- + +# The Configuration File + +The great File of Configuration is truly a mighty hurdle to overcome when implementing this library. It contains many confusing and difficult concepts such as "tags" and "attributes". However, when it comes down to it, it is really just a weird form of layout file that specifies the information to display instead of how to display it. + +For no specific reason, each configuration file must have an `` tag as its root element. Inside of that tag, any amount of children can be defined in any order. When the about screen is opened, these tags will be parsed and their corresponding objects will be created, much like inflating a layout file. The objects are then added to a list to be displayed in a RecyclerView. In order to simplify things, these tags, their corresponding objects, and the views created for them in the RecyclerView will be referred to as "wedges". + +Because wedge classes are instantiated from the configruation file, the wedge's tag in the file must be the class name of the wedge that should be instantiated, including the package name. This is the same as adding a custom view to a layout file. + +With this information, we can now create a simple configuration file using the [`App`](./wedges/app.md), [`Contributors`](./wedges/contributors.md), and [`Licenses`](./wedges/licenses.md) wedges as follows. + +```xml + + + + + + + + + +``` + +This will create a screen that displays information about your app, followed by its contributors and finally the open source licenses that you have used. However, the only information that is currently displayed is what Attribouter knows how to find by itself; the `AppWedge` displays your app's icon, name, and a link to rate your app on the Play Store, the `ContributorsWedge` displays the people that have contributed to Attribouter, and the `LicensesWedge` displays the licenses that Attribouter uses. In order to add information to these wedges, you can use one of the following options: + +## Option 1: The GitHub API + +As stated in their documentation, both the [`AppWedge`](./wedges/app.md) and the [`ContributorsWedge`](./wedges/contributors.md) have an attribute titled `repo` that accepts the full name of a GitHub repository. Let's say that the repository for your app is [TheAndroidMaster/Pasta-for-Spotify](https://jfenn.me/redirects/?t=github&d=Pasta-for-Spotify). In that case, you can modify the file as follows: + +```xml + + + + + + + + + +``` + +The `AppWedge` now displays the repository's description, a link to the Pasta-for-Spotify repository on GitHub, and a link to the project's homepage ([https://jfenn.me/apps/pasta](https://jfenn.me/apps/pasta/)), and the `ContributorsWedge` includes all of [the people that have contributed to it](https://jfenn.me/redirects/?t=github&d=Pasta-for-Spotify/graphs/contributors). + +## Option 2: Attributes and Children + +If your project does not have a GitHub repository or you want some information to be available without an internet connection, you should define that information in the configuration file. Using the documentation pages for `AppWedge` and `ContributorsWedge`, the equivalent of Option 1 (without the GitHub link in the `AppWedge`) would be as follows: + +```xml + + + + + + + + + + + + + + + + + +``` + +## Option 3: Both + +> "This should be fairly easy. All that you need to do is combine the two previous options, right?" + +Actually, there is one extra step - if you do not define the `login` attribute on all of the [`ContributorWedge`](./wedges/contributor.md)s, you will end up with two sets of contributors - one from the configuration file and one from the GitHub API. Similar attributes are used to merge duplicate wedges like [`LinkWedge`](./wedges/link.md)s and [`LicenseWedge`](./wedges/license.md)s, so you should check out ["Overriding Resources and Providing Translations"](../resources.md) if the results of this option confuse you. When you are done, the end result should look something like this: + +```xml + + + + + + + + + + + + + + + + + +``` diff --git a/docs/RESOURCES.md b/docs/resources.md similarity index 80% rename from docs/RESOURCES.md rename to docs/resources.md index 7605363..71cdc4a 100644 --- a/docs/RESOURCES.md +++ b/docs/resources.md @@ -1,19 +1,19 @@ ---- -title: Overriding Resources and Providing Translations ---- - -# Overriding Resources and Providing Translations - -## Problem - -Currently, Attribouter fetches its information from two different locations: the configuration file that you write, and the GitHub API. However, there will occasionally be some information that is provided by both the file and GitHub. Because Attribouter gets the information from the GitHub API shortly after processing the configuration file, the obvious behavior would be to simply replace the information from the configuration file with its GitHub counterpart. However, that isn't a perfect solution, as shown in the following situations: - -- one [`ContributorWedge`](./wedges/CONTRIBUTOR.md) in a [`ContributorsWedge`](./wedges/CONTRIBUTORS.md) does not have a GitHub counterpart, but all of the others do; it would disappear -- a [`ContributorWedge`](./wedges/CONTRIBUTOR.md) has an `email` attribute, but its GitHub counterpart does not provide one; it would disappear -- the [`AppWedge`](./wedges/APP.md)'s `description` attribute is a string resource that is translated into several languages, but the GitHub repositories description is in English; it would always display in English - -## Solution - -In order to work around these situations, rather than simply replacing duplicate information, Attribouter "merges" them together. Using this method, if an attribute is in the configuration file that doesn't have a GitHub counterpart, it is kept, but all others are overwritten. Likewise, [`ContributorWedge`](./wedges/CONTRIBUTOR.md)s inside of a [`ContributorsWedge`](./wedges/CONTRIBUTORS.md) are merged if their `login` attributes match, and are left alone if they do not (ex: contributors in the config file not present on GitHub are left in the list, and contributors not in the config file but present on GitHub are added as well). - -However, you may notice that this solution does not account for the last situation, as it isn't possible to detect this automatically. As a workaround, Attribouter looks for a "^" character at the start of an attribute before merging it. If present, it will ignore its GitHub counterpart. In other words, if the translated string was `@string/app_desc`, the `description` attribute can be set to `^@string/app_desc` to prevent it from being overwritten by the GitHub data. +--- +title: Overriding Resources and Providing Translations +--- + +# Overriding Resources and Providing Translations + +## Problem + +Currently, Attribouter fetches its information from two different locations: the configuration file that you write, and the GitHub API. However, there will occasionally be some information that is provided by both the file and GitHub. Because Attribouter gets the information from the GitHub API shortly after processing the configuration file, the obvious behavior would be to simply replace the information from the configuration file with its GitHub counterpart. However, that isn't a perfect solution, as shown in the following situations: + +- one [`ContributorWedge`](./wedges/contributor.md) in a [`ContributorsWedge`](./wedges/contributors.md) does not have a GitHub counterpart, but all of the others do; it would disappear +- a [`ContributorWedge`](./wedges/contributor.md) has an `email` attribute, but its GitHub counterpart does not provide one; it would disappear +- the [`AppWedge`](./wedges/app.md)'s `description` attribute is a string resource that is translated into several languages, but the GitHub repositories description is in English; it would always display in English + +## Solution + +In order to work around these situations, rather than simply replacing duplicate information, Attribouter "merges" them together. Using this method, if an attribute is in the configuration file that doesn't have a GitHub counterpart, it is kept, but all others are overwritten. Likewise, [`ContributorWedge`](./wedges/contributor.md)s inside of a [`ContributorsWedge`](./wedges/contributors.md) are merged if their `login` attributes match, and are left alone if they do not (ex: contributors in the config file not present on GitHub are left in the list, and contributors not in the config file but present on GitHub are added as well). + +However, you may notice that this solution does not account for the last situation, as it isn't possible to detect this automatically. As a workaround, Attribouter looks for a "^" character at the start of an attribute before merging it. If present, it will ignore its GitHub counterpart. In other words, if the translated string was `@string/app_desc`, the `description` attribute can be set to `^@string/app_desc` to prevent it from being overwritten by the GitHub data. diff --git a/docs/SUBWEDGING.md b/docs/subwedging.md similarity index 97% rename from docs/SUBWEDGING.md rename to docs/subwedging.md index 2b457d6..f17c86c 100644 --- a/docs/SUBWEDGING.md +++ b/docs/subwedging.md @@ -1,133 +1,133 @@ ---- -title: Extending a Wedge ---- - -# Extending a Wedge - -Since the wedges used in the layout file are referenced by their corresponding class name, you may have guessed that it is possible to create your own wedge similarly to how one would create a custom view. You would be correct in that assumption. That said, because there are so many different use cases for this, I'm not going to provide a full "tutorial", but rather explain the basics of how wedges can be created. - -## Creating the Class - -The absolute minimum requirements for a wedge class are that they must extend `me.jfenn.attribouter.wedges.Wedge` and have a public constructor that accepts an `android.content.res.XmlResourceParser`. However, there are several additional suggestions that can affect... things... if they are not followed: - -- Because wedges are added to a `RecyclerView`, they can have a subclass extending `me.jfenn.attribouter.wedges.Wedge$ViewHolder`, though this is not required. This class can be defined as a generic type of the `Wedge` class that your wedge class is extending, if that makes any sense (I don't know what I'm saying, just look at the example below and you'll see what I mean). -- Inside the constructor, you must call `super()` with the resource of the layout file that you want your wedge to use. -- You can then use the instance of `XmlResourceParser` to collect any XML arguments you want. -- After this, your constructor should end with a call to `addChildren(XmlResourceParser)`, which will parse and add any child wedges to a list that you can access (if your element has child wedges and there is not a call to this method in your constructor, it is very likely that you will encounter several issues as a result). - -Here is a basic example of what has been described so far: - -```java -public class MyWedge extends Wedge { - - public MyWedge(XmlResourceParser parser) { - super(R.layout.my_wedge_layout); - //get attributes - addChildren(parser); - } - - //other methods - - public static class MyViewHolder extends ViewHolder { - - public MyViewHolder(View v) { - super(v); - } - - } - -} -``` - -## Implementing Methods - -There are also several abstract methods in `Wedge` that must be defined. Rather than explain all of them, I will simply implement them all in the above example along with comments explaining what should happen where. - -```java -public class MyWedge extends Wedge { - - //define information in your Wedge class - - public MyWedge(XmlResourceParser parser) { - super(R.layout.my_wedge_layout); - //instantiate attributes - addChildren(parser); - } - - @Override - public MyViewHolder getViewHolder(View v) { //"v" is the inflated layout file that you passed the resource of in your call to super() - return new MyViewHolder(v); //yep, that's all you really need - } - - @Override - public void bind(Context context, MyViewHolder viewHolder) { - //here you bind the data in your wedge class to the views in the MyViewHolder instance - } - - public static class MyViewHolder extends ViewHolder { - - //define views in your layout - - public MyViewHolder(View v) { - super(v); - //instantiate views - "view = v.findViewById(...);" - } - - } - -} -``` - -## GitHub Requests - -If you wish to make a request to the GitHub API from your wedge, simply call `addRequest(GitHubData)` with an instance of one of the [classes extending GitHubData](../attribouter/src/main/java/me/jfenn/attribouter/data/github/), or you can create your own. Thanks to [GSON](https://github.com/google/gson)'s magic, this is ridiculously simple, and if you've gotten this far you can probably figure it out yourself just by looking at the source code. - -After calling `addRequest()` with an instance of `GitHubData`, Attribouter will obtain and parse the data itself (as well as caching, combining duplicate requests, and other complicated things), and will pass it back to the `onInit(GitHubData)` method - which you should probably extend - of your wedge class, where you can modify any of your wedge's data with the information you have obtained. Once `onInit` has been called, Attribouter will notify the RecyclerView of a change to your wedge, and you wedge's `bind()` method will be called shortly afterwards. - - As an example, here is a wedge based on the previous examples that initially displays my name in a TextView as "James Fern", then makes a request to GitHub, correcting it to "James Fenn": - - ```java -public class MyWedge extends Wedge { - - private String myName; - - public MyWedge(XmlResourceParser parser) { - super(R.layout.this_is_a_textview); - - myName = "James Fern"; - addRequest(new UserData("TheAndroidMaster")); - - addChildren(parser); - } - - @Override - public MyViewHolder getViewHolder(View v) { - return new MyViewHolder(v); - } - - @Override - public void bind(Context context, MyViewHolder viewHolder) { - viewHolder.textView.setText(myName); - } - - @Override - public void onInit(GitHubData data) { - if (data instanceof UserData) { - UserData user = (UserData) data; - myName = user.name; - } - } - - public static class MyViewHolder extends ViewHolder { - - TextView textView; - - public MyViewHolder(View v) { - super(v); - textView = (TextView) v; - } - - } - -} -``` +--- +title: Extending a Wedge +--- + +# Extending a Wedge + +Since the wedges used in the layout file are referenced by their corresponding class name, you may have guessed that it is possible to create your own wedge similarly to how one would create a custom view. You would be correct in that assumption. That said, because there are so many different use cases for this, I'm not going to provide a full "tutorial", but rather explain the basics of how wedges can be created. + +## Creating the Class + +The absolute minimum requirements for a wedge class are that they must extend `me.jfenn.attribouter.wedges.Wedge` and have a public constructor that accepts an `android.content.res.XmlResourceParser`. However, there are several additional suggestions that can affect... things... if they are not followed: + +- Because wedges are added to a `RecyclerView`, they can have a subclass extending `me.jfenn.attribouter.wedges.Wedge$ViewHolder`, though this is not required. This class can be defined as a generic type of the `Wedge` class that your wedge class is extending, if that makes any sense (I don't know what I'm saying, just look at the example below and you'll see what I mean). +- Inside the constructor, you must call `super()` with the resource of the layout file that you want your wedge to use. +- You can then use the instance of `XmlResourceParser` to collect any XML arguments you want. +- After this, your constructor should end with a call to `addChildren(XmlResourceParser)`, which will parse and add any child wedges to a list that you can access (if your element has child wedges and there is not a call to this method in your constructor, it is very likely that you will encounter several issues as a result). + +Here is a basic example of what has been described so far: + +```java +public class MyWedge extends Wedge { + + public MyWedge(XmlResourceParser parser) { + super(R.layout.my_wedge_layout); + //get attributes + addChildren(parser); + } + + //other methods + + public static class MyViewHolder extends ViewHolder { + + public MyViewHolder(View v) { + super(v); + } + + } + +} +``` + +## Implementing Methods + +There are also several abstract methods in `Wedge` that must be defined. Rather than explain all of them, I will simply implement them all in the above example along with comments explaining what should happen where. + +```java +public class MyWedge extends Wedge { + + //define information in your Wedge class + + public MyWedge(XmlResourceParser parser) { + super(R.layout.my_wedge_layout); + //instantiate attributes + addChildren(parser); + } + + @Override + public MyViewHolder getViewHolder(View v) { //"v" is the inflated layout file that you passed the resource of in your call to super() + return new MyViewHolder(v); //yep, that's all you really need + } + + @Override + public void bind(Context context, MyViewHolder viewHolder) { + //here you bind the data in your wedge class to the views in the MyViewHolder instance + } + + public static class MyViewHolder extends ViewHolder { + + //define views in your layout + + public MyViewHolder(View v) { + super(v); + //instantiate views - "view = v.findViewById(...);" + } + + } + +} +``` + +## GitHub Requests + +If you wish to make a request to the GitHub API from your wedge, simply call `addRequest(GitHubData)` with an instance of one of the [classes extending GitHubData](../attribouter/src/main/java/me/jfenn/attribouter/data/github/), or you can create your own. Thanks to [GSON](https://github.com/google/gson)'s magic, this is ridiculously simple, and if you've gotten this far you can probably figure it out yourself just by looking at the source code. + +After calling `addRequest()` with an instance of `GitHubData`, Attribouter will obtain and parse the data itself (as well as caching, combining duplicate requests, and other complicated things), and will pass it back to the `onInit(GitHubData)` method - which you should probably extend - of your wedge class, where you can modify any of your wedge's data with the information you have obtained. Once `onInit` has been called, Attribouter will notify the RecyclerView of a change to your wedge, and you wedge's `bind()` method will be called shortly afterwards. + + As an example, here is a wedge based on the previous examples that initially displays my name in a TextView as "James Fern", then makes a request to GitHub, correcting it to "James Fenn": + + ```java +public class MyWedge extends Wedge { + + private String myName; + + public MyWedge(XmlResourceParser parser) { + super(R.layout.this_is_a_textview); + + myName = "James Fern"; + addRequest(new UserData("TheAndroidMaster")); + + addChildren(parser); + } + + @Override + public MyViewHolder getViewHolder(View v) { + return new MyViewHolder(v); + } + + @Override + public void bind(Context context, MyViewHolder viewHolder) { + viewHolder.textView.setText(myName); + } + + @Override + public void onInit(GitHubData data) { + if (data instanceof UserData) { + UserData user = (UserData) data; + myName = user.name; + } + } + + public static class MyViewHolder extends ViewHolder { + + TextView textView; + + public MyViewHolder(View v) { + super(v); + textView = (TextView) v; + } + + } + +} +``` diff --git a/docs/THEMING.md b/docs/theming.md similarity index 95% rename from docs/THEMING.md rename to docs/theming.md index 56bdba4..ddf2c34 100644 --- a/docs/THEMING.md +++ b/docs/theming.md @@ -1,41 +1,41 @@ ---- -title: Custom Themes ---- - -## Activity / Dialog Themes - -By default, Attribouter uses an extension of `Theme.AppCompat.Light.NoActionBar` as its activity theme. The contributor and license dialogs use `ThemeOverlay.AppCompat.Dialog`, and fullscreen dialogs (overflow screens) use an extension of the activity theme with a window animation. - -There are multiple ways that you can change these themes, but I know that this one works, so I am going to do this. If you are using Attribouter as a fragment, you can skip the first part since it will use whatever theme you have set for the activity that the fragment is in. - -### Overriding the Activity Theme - -First, add a new style resource to your `styles.xml` titled "AttribouterTheme". This will override the theme defined by Attribouter that it uses by default. The theme's parent should be "Theme.AppCompat.something", preferably ending with ".NoActionBar" since Attribouter's activity has one of its own. For example, if you wanted to use a dark theme, you would use `Theme.AppCompat.NoActionBar` as follows: - -```xml - - - - + +