Edit recommendation: Rare earth Nuggets, this is an application for technical developers, you can get the latest and best quality technology nuggets, not only Android knowledge, front-end, back-end as well as products and design dabbler, want to become a friend of full stack engineers do not miss it!

From Design to Android, Part 1

Thanks to design platforms like Dribbble and MaterialUp, we developers have access to a wealth of conceptual design resources. However, sometimes some details are almost impossible to implement, and parts of the user experience are not considered.

For this reason, I thought it would be interesting to set up a project that would select some design resources from Dribbble or MaterialUp, implement them on Android, and then write a series of articles explaining the implementation details and what I think are the most important android interface implementation techniques.

The conceptual design

This is the concept design I chose for Part 1, simple but enough to cover some interesting topics like ConstraintLayout & Chains, DataBinding, the importance of UI hierarchy performance, and scenes.

  • The conceptual design was written by Johnyvino and published on MaterialUp.

  • The implementation can be found at the GitHub repository.

Let’s get started!

Support for Bottom sheets in the library

In the demo, The Bottom Sheet is used to guide the user through the purchase process. You can find several third-party libraries in Android to implement this view, such as Umano’s AndroidSlidingUpPanel Library.

In fact, Recently Bottoms Sheets have been introduced into the Design Support library, so I decide to use it here and learn how to use it.

Bottom sheets can be used in two ways, either as part of the main view (BottomSheetBehavior is used on a viewgroup in CoordinatorLayout), The other is a modal dialog box like Bottom sheets, use BottomSheetDialogFragment to implement.

I choose BottomSheetDialogFragment for our example, because the information is showed in the form of the modal. The Bottom Sheets implementation code is similar to the DialogFragment usage.

HomeActivity.java

OrderDialogFragment.newInstance(
  fakeProducts.get(position))
    .show(getSupportFragmentManager(),null);Copy the code

OrderDialogFragment.java

  @Override
public View onCreateView(LayoutInflater inflater,
    ViewGroup container,Bundle savedInstanceState) {
 
    super.onCreateView(inflater,
        container, savedInstanceState);
 
    binding = FragmentOrderFormBinding.inflate(
        inflater, container, false);
 
    return binding.getRoot();
}Copy the code

ConstraintLayout

The powerful layout control released on Google I/O ’16 recently received its stable release (1.0.2).

The great benefit of this control is that it allows you to construct complex, adaptive layouts at the flattenest possible levels.

It is generally recommended to avoid using deep view structures in Android layouts, as this can reduce performance and increase the time it takes to draw the UI to the screen. With ConstraintLayout, this requirement is automatically satisfied.

Basically, ConstraintLayout works like a RelativeLayout, which defines the relationship between the view and the screen. But ConstraintLayout, in addition to performing better, also works really well in Android Studio’s graphics editor.

There are also more interesting mechanisms such as chain between views (different views constrain each other) or guidelines.

The use of the chain

Suppose we have two views, A and B, constrained on the right and left edges of the screen respectively. If A is set to the left of B and B is set to the right of A, the set of views will be treated specially. In constrained layouts, this case is called A chain.

You can easily create a chain using the context menu in Android Studio’s layout editor. By default, the spread chain is created, which means the view is evenly distributed.

Chain type


In this example, we only use spread and Packed Chain, but you can choose according to your needs, recently Google pairsConstraintLayoutDocumentation added to the pairchainThere’s no reason not to.

The transition animation of the selected view

This seems relatively simple; every time the user clicks on a product parameter, the selected view transitions to the bottom left corner next to the label.

To do this we add a new view to the parent of the clicked view.

OrderDialogFragment.java

private void transitionSelectedView(View v) {
    final View selectionView = createSelectionView(v);
 
    binding.mainContainer.addView(selectionView);
 
    startCloneAnimation(selectionView, getTargetView(v));
}Copy the code

Then use beginDelayedTransition of TransitionManager to animate the transition. This method will detect if the layout has changed, and if so, use the transition passed in to perform the animation.

OrderDialogFragment.java

private void startCloneAnimation(View clonedView, View targetView) { clonedView.post(() -> { TransitionManager.beginDelayedTransition( (ViewGroup) binding.getRoot(), selectedViewTransition); / / triggers the transition clonedView. SetLayoutParams (SelectedParamsFactory endParams (clonedView targetView)); }); }Copy the code

ViewSwitcher

ViewSwitcher, an Android SDK control that is not very popular, it can switch between two views using enter and exit animation. This is perfectly consistent with switching between layouts that represent two steps in our purchase process. fragment_order_form.xml


 
    
 
    
Copy the code

OrderDialogFragment.java

private void showDeliveryForm() {
    binding.switcher.setDisplayedChild(1);
    initOrderStepTwoView(binding.layoutStep2);
}Copy the code

Databinding (Databinding)

I used Databinding for the implementation of this design, and it is acceptable for me to have all the layout structure in one object, but Databading has a few other mechanisms worth mentioning.

Save click Listener writing times

Because these layouts have a lot of listeners to handle, I decide to bind a Listener object with Databinding to handle onClick. In XML, you set the method name for each view’s onClick property, and the event is directed to the corresponding method on the Listener object.

layout_form_order_step1.xml

<data>
    <variable
        name="listener"
        type="com.saulmm.cui.OrderDialogFragment.Step1Listener"
        />
</data>
 
<CircleImageView
    android:id="@+id/img_color_blue"
    style="@style/Widget.Color"
    android:onClick="@{listener::onColorSelected}"
    />
 
<CircleImageView
    android:id="@+id/img_color_blue"
    style="@style/Widget.Color"
    android:onClick="@{listener::onColorSelected}"
    />Copy the code

OrderDialogFragment.java

layoutStep1Binding.setListener(new Step1Listener() { @Override public void onSizeSelected(View v) { // ... } @Override public void onColorSelected(View v) { // ... }})Copy the code

Use Spannables + databinding + ConstraintLayout to reduce views

Let’s take a moment to think about how to implement this part of the design

One way is to set up a vertical LinearLayout for each item. Then the three items are contained in a horizontal LinearLayout, and then wrap the two horizontal LinearLayouts and two text label controls with a LinearLayout.

Don’t do that normally

It doesn’t look good, does it? We talked earlier about the importance of flat structures, so the correct approach is to use ConstrainLayout as a container.

Each item is a LinearLayout, which is very expensive. In fact, we just want to display text with different font sizes, maybe adding a border or something. We can make each item only have one TextView control.

Spannables

Spannables allow text to be displayed in different sizes, and borders can be drawn using drawable. In this way, we can save 3 views for each item, which is far better than the first method.

The problem with using Spannables is that time items have different numbers of large characters than date items.

Using Databinding and its BindingAdapters mechanism, you can create a property that sets the number of large characters.

layout_form_order_step2.xml

<TextView
    android:id="@+id/txt_time1"
    style="@style/Widget.DateTime"
    app:spanOffset="@{3}"
    />
 
<TextView
    android:id="@+id/txt_date1"
    style="@style/Widget.DateTime"
    app:spanOffset="@{2}"/>Copy the code

OrderDialogFragment.java

@BindingAdapter("app:spanOffset") public static void setItemSpan(View v, int spanOffset) { final String itemText = ((TextView) v).getText().toString(); final SpannableString sString = new SpannableString(itemText); Sstring.setspan (New RelativeSizeSpan(1.75f), ItemText.length () -spanoffset, ItemText.length (), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); ((TextView) v).setText(sString); }Copy the code

“Scenes”

Perhaps the essence of implementing the following concept is how to transition between the book button and the confirmation view.

It’s not that hard, if we use the smoke screen. If we think of the button not as a button but as a container, we realize that we can use scenes to do this animation.

The entire form is the first scene, the confirmation view is the second scene, and the button is a shared element between the two interfaces. A shared element is a view shared between two scenes, and the framework uses a transition to animate the view appropriately.


Once we know that the logic is to change two scenes, the problem becomes simple.

OrderDialogFragment.java

private void changeToConfirmScene() {
    final LayoutOrderConfirmationBinding confBinding =
        prepareConfirmationBinding();
 
    final Scene scene = new Scene(binding.content,
        ((ViewGroup) confBinding.getRoot()));
 
    scene.setEnterAction(onEnterConfirmScene(confBinding));
 
    final Transition transition = TransitionInflater
        .from(getContext()).inflateTransition(
              R.transition.transition_confirmation_view);
 
    TransitionManager.go(scene, transition);
}Copy the code

The effect

reference

  • ConstraintLayout Documentation – Android developers

  • Mastering android drawables – Cyril Mottier

  • Efficient android layouts – Dan Lew

  • Plaid – Nick Butcher