Tuesday, 4 October 2016

Working With GuidedStepFragment on Android TV

Screen 1

Settings page like update profile

In my previous blog, I had given you the brief idea about the GuidedStepFragment, and modify its basic override method to use it as confirmation dialog on android TV.

Today in this post we will learn about the various actions to perform desire views task which happen in android mobile.
So, here we are going to start,

Editable Description Fields

Screen -2 
It's now possible to input text in an action. Have you ever tried entering your email on TV with remote? Use GuidedAction.Builder.descriptionEditable(true) to make your actions editable. You can listen for completion on this field via  onGuidedActionEditedAndProceed . You will all see  GuidedAction.Builder.descriptionInputType in this to provide keyboard type.
I have created small actionable methods for the ease of usage , i.e.
private static void addEditable(List<GuidedAction> actions, int iconResId, Context context,
                                String title, String desc) {
    actions.add(new GuidedAction.Builder()
            .id(iconResId)
            .title(title)
            .descriptionEditable(true)
            .description(desc)
            .build());
}

GuidedAction SubAction Drop Down

Screen - 3
This has feature of drop down and selecting particular option and editing to main action's description. All you need to use is GuidedAction.Builder.subActions to add more sub actions to your main action. You can listen to any of your sub action by overriding GuidedStepFragment.onSubActionClicked. Here is my code for showing drop down as in screen - 3:
private static void addCheckedSubAction(List<GuidedAction> actions, int id, String title,
 String desc, boolean checked) {
    GuidedAction guidedAction = new GuidedAction.Builder()
            .title(title)
            .description(desc)
            .checkSetId(OPTION_CHECK_SET_ID)
            .build();
    guidedAction.setChecked(checked);
    actions.add(guidedAction);
}
private static void addDropDownAction(List<GuidedAction> actions, long id, String title,
 String desc, List<GuidedAction> selectionActions) {
    actions.add(new GuidedAction.Builder()
            .id(id)
            .title(title)
            .description(desc)
            .subActions(selectionActions)
            .build());
}

Guided Date Picker Action

Screen - 4

Simply put, this is just a date picker within action view just like editable Guided Actions.
You listen for completion from within the onGuidedActionEditedAndProceed method.
Here is my implementation.
private static void addDateAction(Context context, List<GuidedAction> actions, 
long id, String title, long date) {
    actions.add(new GuidedDatePickerAction.Builder(context)
            .id(id)
            .date(date)
            .datePickerFormat("DMY")
            .maxDate(new Date().getTime())
            .title(title)
            .build());
}

I am providing you the full working code for screen -1
public static class UpdateProfileStepFragment extends GuidedStepFragment {
        String name, mDob, email, mGender;
private static final int NAME = 0;
private static final int EMAIL = 1;
private static final int DOB = 2;
private static final int MALE = 3;
private static final int FEMALE = 4;
private static final int ACTION_GENDER = 5;

private static final int OK = 6;
public static UpdateProfileStepFragment newInstance(final int option) { final UpdateProfileStepFragment f = new UpdateProfileStepFragment(); // final Bundle args = new Bundle();// args.putInt(ARG_OPTION_IDX, option);// f.setArguments(args); return f; } @Override
     @NonNull   
     public Guidance onCreateGuidance(Bundle savedInstanceState) {

            String title = "Update Profile";
            String email = "your email";

            String description = email;

            return new Guidance(title, description, null, null);
        }

        @Override   
     public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
            name = "name";
            email = "email";
            mDob = "01/01/1980";
            long dob = 0;
            mGender = "";
            if (mGender != null && !TextUtils.isEmpty(mGender) && mGender.equalsIgnoreCase("female")) {
                isMale = false;
            }
            Calendar calendar = Calendar.getInstance();
          
                    dob = calendar.getTime().getTime();
               
            addEditable(actions, NAME, getActivity(), "Name", name);
            addEditable(actions, EMAIL, getActivity(), "Email", email);
            addDateAction(getActivity(), actions, DOB, "Date of Birth", dob);

            List<GuidedAction> genderActions = new ArrayList<>();
            if (isMale) {
                mGender = "Male";
                addCheckedAction(genderActions, MALE, "Male", "", true);
                addCheckedAction(genderActions, FEMALE, "Female", "", false);
            } else {
                mGender = "Female";
                addCheckedAction(genderActions, MALE, "Male", "", false);
                addCheckedAction(genderActions, FEMALE, "Female", "", true);
            }

            addDropDownAction(actions, ACTION_GENDER, "Gender", mGender, genderActions);
            addAction(actions, OK, getString(R.string.ok), "");
            addAction(actions, BACK, "Cancel", "");

        }


        @Override        public boolean onSubGuidedActionClicked(GuidedAction action) {
            if (action.getLabel1().toString().equalsIgnoreCase("male")) {
                isMale = true;
                mGender = "Male";
                findActionById(ACTION_GENDER).setDescription("Male");
                notifyActionChanged(findActionPositionById(ACTION_GENDER));
            } else if (action.getLabel1().toString().equalsIgnoreCase("female")) {
                isMale = false;
                mGender = "Female";
                findActionById(ACTION_GENDER).setDescription("Female");
                notifyActionChanged(findActionPositionById(ACTION_GENDER));

            }

            return super.onSubGuidedActionClicked(action);
        }

        @Override        public void onGuidedActionClicked(GuidedAction action) {
            if (action.getId() == OK) {
            } else if (action.getLabel1().toString().equalsIgnoreCase("Cancel")) {
                getActivity().finish();

            }

        }

        @SuppressLint("LongLogTag")
        @Override    
    public long onGuidedActionEditedAndProceed(GuidedAction action) {
            if (action.getId() == NAME) {
                name = action.getDescription().toString();
            } else if (action.getId() == EMAIL) {
                email = action.getDescription().toString();

            } else if (action.getId() == DOB) {
                GuidedDatePickerAction daction = (GuidedDatePickerAction) action;
               
               Log.d(TAG, "onGuidedActionClicked() [ACTION_DOB] : " + 
new Date(daction.getDate()));            }
            return super.onGuidedActionEditedAndProceed(action);
        }
}


If i have missed something, feel free to write in comments and let me know.



















Sunday, 2 October 2016

Android TV - Dialog


The leanback library for Android TV introduced the concept of guided step fragments. These have an intuitive way of presenting prompts to a user. I made a simple class that uses a GuidedStepFragment to create a simple yes/no dialog for TV. check out the code for this below:

Add declaration of this Activity to AndroidManifest.
<activity  
android:name="ATVDialog"  
android:theme="@style/Theme.Example.Leanback.GuidedStep" />

So we can start implementing GuidedStepFragment from here. Before real implementation, I will tell you basic structure of this GuidedStepFragment in brief :

GuidedStepFragment – Structure

As mentioned in official_doc, It is composed of a guidance view on the left and a view on the right containing a list of possible actions.

Overriding Method

To use GuidedStepFragment, we need to override at least these 3 methods.

  • onCreateGuidance(Bundle) – To create guidance view (left side).  – Attributes of guidance (title, description etc) are specified here.
  • onCreateActions(List, Bundle) – To define list of possible actions (right side). – Attributes of action are specified here.
  • onGuidedActionClicked(GuidedAction) – This is onClick listener. – Behaviors after clicking action buttons can be specified here.

At least if you know this, you can use GuidedStepFragment. But you may want to modify the design layout of this Guidance. You can use “Theme” & “Stylist” to customize visual styling

Implementation (Overriding method)

To attach instance of GuidedStepFragment, we can use GuidedStepFragment.add function. Here instance of ConfirmationStepFragment class, which is a subclass of GuidedStepFragment, is added at onCreate of ATVDialog.
Please also check the sample implementation of 3 overriding methods such as, onCreateGuidance, onCreateActions and onGuidedActionClicked.


public class ATVDialog extends Activity {
    private static final int CONTINUE = 0;
    private static final int BACK = 1;
   
    @Override  
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (null == savedInstanceState) {
           
                GuidedStepFragment.addAsRoot(this, new ConfirmationStepFragment(),
             android.R.id.content);
           
        }
    
    }

    private static void addAction(List<GuidedAction> actions, long id, 
     String title, String desc) {
        actions.add(new GuidedAction.Builder()
                .id(id)
                .title(title)
                .description(desc)
                .build());
    }

public static class ConfirmationStepFragment extends GuidedStepFragment {

        @Override
        @NonNull     
        public Guidance onCreateGuidance(@NonNull Bundle savedInstanceState) {
            String title = "Confirm";
            String description = "Dialog description message";
            return new Guidance(title, description, null, null);
        }

        @Override       
      public void onCreateActions(@NonNull List<GuidedAction> actions,
          Bundle savedInstanceState) {
            addAction(actions, CONTINUE,
                    "Confirm",
                    null);
            addAction(actions, BACK,
                    "Cancel",
                    null);
        }

        @Override   
        public void onGuidedActionClicked(GuidedAction action) {
            FragmentManager fm = getFragmentManager();
            if (action.getId() == CONTINUE) {
               //Do action on confirm Click
            } else {
                getActivity().finish();
                  }
        }
}
}





Apple Glass Concept

Apple Glass Concept Shows Us All the AR Goodness We Need These days  smart glasses  are back in full force, courtesy of so...