Friday, July 31, 2015

Data Validation of Numeric Edit Text in Android

After spending some time to learn Material design, I felt it would be worth my time to take a break and focus on actually getting data onto my app and start progressing, then do a design pass later. I was churning my wheels trying to get all the character attributes set up and decided it was best to just get something on paper. I settled on a TableLayout to organize the labels from the character attributes and modifiers. I also did a bit of playing with design and cleanup and had something at least organized:

Overall this is rather respectable, it has a semi clean look and gives logical organization of the data. Am I in love with it? No, but it is something. The biggest challenge was getting the labels to stretch across the entirety of the view, instead of getting clumped. It took a bit of searching, but I found this attribute:

android:stretchColumns

Which made all the difference. It allowed me to get the desired spread. I likely should revisit the spacing size of the central Numeric EditText but since this is more placeholder I say sufficient for now.

The next big step was setting it so that when the user sets his Attribute value, it would auto update the modifier on the back end. The initial setup was not terrible, you hook up a "TextChanged" event handler, grab the values, update accordingly.

        void OnStrengthChanged (object sender, Android.Text.TextChangedEventArgs e)
{ 

     var numField = (EditText)sender;
     var value = int.Parse (numField.Text);
     characterData.SetSingleAttribute (new Attributes{ Strength = value });

     var mod = FindViewById<TextView> (Resource.Id.strengthMod);
     mod.Text = testCharacter.FinalAttributes.StrengthModifier.ToString ();

}

Overall, rather straight forward. I currently store Attributes as a single object that contains the individual properties for both Values and modifiers, basically a special array container with some validation inside. "characterData" is my storage for all applicable data. All of that is defined in my shared PCL. I think this is an area that could use a refactor. Currently my SetSingleAttribute is something like this:

        public void SetSingleAttribute(Attributes attributes)
        {
            baseAttributes.Strength = attributes.Strength == 0 ? baseAttributes.Strength : attributes.Strength;
            baseAttributes.Dexterity = attributes.Dexterity == 0 ? baseAttributes.Dexterity : attributes.Dexterity;
            baseAttributes.Constitution = attributes.Constitution == 0 ? baseAttributes.Constitution : attributes.Constitution;
            baseAttributes.Intelligence = attributes.Intelligence == 0 ? baseAttributes.Intelligence : attributes.Intelligence;
            baseAttributes.Wisdom = attributes.Wisdom == 0 ? baseAttributes.Wisdom : attributes.Wisdom;
            baseAttributes.Charisma = attributes.Charisma == 0 ? baseAttributes.Charisma : attributes.Charisma;

            baseAttributes = baseAttributes - Race.BonusAttributes;
        }







Basically I find the attribute that has been modified as all the others have been nulled out. I need to spend some more time on this, especially once I implement racial and feat bonuses. For now, it gets things moving forward while I block out all the data.

One challenge that I ran into was editing attribute values. The default behavior when clicking these fields (as they are just text fields) is to allow the user to edit the entry. To handle the scenario where a user deletes the existing values, I was running into an awkward case of trying to convert an empty string to a number, which does not work very well, and left an unintuitive experience. What I did to solve it was set the fields "Hint" parameter:

strValue.Hint = "8"; 

Then you get a nice greyed out sample field, without disrupting your flow:
As you can see, there is a nice greyed entry, more intuitive.
This is definitely coming along well. For some preliminary data validation I also set maxLength to 2 to prevent numbers larger than 2 digits. Ideally I  should limit to something like 6-20 as per the rules, but it is a start. As a note, a more complete complete implementation would use either a custom class of EditText or InputFilters.


Friday, July 17, 2015

Creating Custom Views with a Spinner

The next step in my app was making a quick cosmetic change. If you recall my drop downs for Race and Character classes were left text aligned. This is due to the default Resource settings I was used at its creation. Creating spinners, there are two layout settings that I discovered you can play with.

Spinner races = FindViewById <Spinner> (Resource.Id.charRace);
var adapter = new ArrayAdapter<string> (this, Android.Resource.Layout.SimpleSpinnerItem1, items);
adapter.SetDropDownViewResource (Android.Resource.Layout.SimpleSpinnerDropDownItem );


When you create a Spinner control, you have to set its adapter, which basically determines how it displays the data added, and will tell the Spinner what type of data objects it should expect. The above was my original code.

The first line finds the Spinner in the Android Resources, the second initializes the Adapter to contain/expect an array of type string, and the third sets the display of the individual items when you click the spinner and dropdown. Digging around, I learned it should be as simple as overriding the default Android.Resource.Layout to use a custom layout instead of a default one. Pretty straightforward right? So I created a new android .axml called spinner_item with the following code:

xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="right" />


as all I needed was right aligned text. Problem was, when I tried to reference it, I was getting compile errors:

var adapter = new ArrayAdapter<string> (this, Android.Resource.Layout.spinner_item, items);

This was confusing as everything I read said this should work. It was then, digging through Xamarins documentation that I realized I was missing something:

http://developer.xamarin.com/guides/android/application_fundamentals/resources_in_android/part_1_-_android_resource_basics/ 

When referencing resources programmatically (in code), they can be accessed via the Resources class hierarchy which uses the following syntax:
@[.]Resource..

I noticed I was using Android.Resource.Layout, key word being "ANDROID", or the default resources. Since I was using resources local to my own project, I could just say

Resource.Layout.spinner_item and this would find my new custom layout. Adding that we get this:
var adapter = new ArrayAdapter<string> (this, Resource.Layout.spinner_item, items);  

 And we get the following:

This looks much better, and a lot cleaner due to how the combo boxes are displaying the data. I am still debating whether or not this falls in line with Material design but for now I am content with it, it looks clean. I have since decided that this is a first pass and so I will likely do a "good enough" approach to get my information visible and then do a full pass pater to get things better organized.






Wednesday, July 1, 2015

Getting Started with App development, Android and Material Design

Seeing that I joined the ranks of the Xamarin Certified Developers last month, and working as a Sales Engineer at Xamarin, I figured it was about time to actually try my hand at building an app. Upon getting started I quickly realized that it is one thing to know all the pieces and the technical theory behind development, it is another to actually be capable of using it in practice.

For now, my goal is to work on an Android app which will ultimately be scaled to include iOS, (Maybe Windows Phone), and then write different technical aspects and learn things like Xamarin.Forms, MVVM Cross, Azure Mobile Services and others. Really it will just be my attempts to be more active in the development community.

The current app I have planned will be themed after a Character Sheet for Dungeons and Dragons, using the 5th generation ruleset. Nerdy, but rather straight forward in its use case.

If you would like to follow the app, you can find the Github repository here:

https://github.com/psycosyd/DnD5e_CBMobile

Getting started, one of my biggest stumbling blocks has actually been UI design and development. Normally I am a huge fan of UI development and design but I admit that Android is not the most intuitive, nor simple.

Part of the problem is theory vs implementation. Google has really done a wonderful job driving direction through their documents on Material Design, found here:

http://www.google.com/design/spec/material-design/introduction.html

It helps give good clarity, color, layout and foundational principles to creating a great android application.
I'm glad you have this great mock up, but where do I sign up for this?

The problem is, while it gives some great rules to follow, it is not as helpful on how the job gets done. As I started this process on my own Dungeons and Dragons app, this is what I started seeing:
I don't know about you, but something seems lacking. I can't quite tell
The big missing factor is the bridge between design and implementation. I conceptually get what Google is preaching, but have no foundation on how to make it happen. Luckily, I am a rather stubborn individual, and like to hammer at something until it works. One thing that I found helped was to start organizing/grouping logical data groups into CardViews. Additionally, coloring backgrounds helped to visually display where my layouts were being positioned.

A couple new factors coming into play here. The CardViews added a nice layer to group logical data. I also had to do some discovery with RelativeLayout and positioning. I had to right justify my entry/input fields, and then centered them by aligning their baselines to the labels on the left. Much cleaner. Now to do a custom adapter to my Spinner controls so we don't have obvious whitespace and we are in business!

To get the top portion organized, most of my actual layout placement was done with my settings using layout_below, alignParentRight (on the right hand elements), and alignBaseLine to get each row lined up. You can see code below:

           <TextView
                android:text="Character Level:"
                android:id="@+id/charLevelLabel"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/charName"
                android:textSize="@dimen/textTitle" />
           <EditText
                android:id="@+id/charLevel"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_alignBaseline="@id/charLevelLabel"
                android:numeric="integer" />



Still this is a promising start. This next week will focus on getting a custom adapter set up for my spinner controls as well as work on the attributes layout, and code behind. Most of this initial phase has been just blocking UI and getting basic pairings set up.