home.


Tagged: android


Android: Detect a fling

If you want to detect a fling on a view, create a GestureDetector that for an argument takes a SimpleOnGestureListener.

final static GestureDetector.SimpleOnGestureListener simpleDetector = new GestureDetector.SimpleOnGestureListener() {
    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        super.onFling(e1, e2, velocityX, velocityY);
        Log.d("HI", "on fling");
        return true; // If you've consumed it
    }
};
final static GestureDetector detector = new GestureDetector(simpleDetector);

It’s within these methods you calculate what kind of fling it is.

Within your onTouch event listener return with return detector.onTouchEvent(motionEvent);.

And make sure the view you’re listening on is clickable. And that should be it.

android android-fling

Android: Simple view dragging tutorial

Let’s say you’ve added a touch listener to a view. And in that listener you have a motionEvent.

Use this code to start dragging that view in onTouch.

if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
    ClipData data = ClipData.newPlainText("", "");
    View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(
            view);
    view.startDrag(data, shadowBuilder, view, 0);
    return true;
} else {
    return false;
}

The clipdata is the data passed to the drop area. And the shadowBuilder is what the view looks like when dragged.

There’s no drop area, but you can look that up.

android android-drag-drop

Android and Facebook's Litho: Getting started

Litho allows you to declare your view in code with speed optimisations for lists.

It uses flexbox layout logic, via the Facebook Yoga library, allowing you to use your existing web knowledge. This applies to iOS too since Yoga also exists for iOS.

It supports one-directional data binding, thereby allowing you dive into the flux architecture a little.

Let’s do the basic getting started first. Let’s bung all the depenedencies into your app’s build.gradle.

compile 'com.facebook.litho:litho-core:0.2.0'
compile 'com.facebook.litho:litho-widget:0.2.0'
provided 'com.facebook.litho:litho-annotations:0.2.0'
annotationProcessor 'com.facebook.litho:litho-processor:0.2.0'
compile 'com.facebook.soloader:soloader:0.2.0'
debugCompile 'com.facebook.litho:litho-stetho:0.2.0'
compile 'com.facebook.litho:litho-fresco:0.2.0'

Create an Application class in your app and ensure your manifest points to it. In the onCreate method add this:

SoLoader.init(this, false);

In your Activity’s onCreate change the view layout code to:

 ComponentContext c = new ComponentContext(this);
 setContentView(LithoView.create(c, MyComponent.create(c).build()));

We’re creating a Litho context, and then creating a Litho view with that context, and a component too. Where does that MyComponent come from?

@LayoutSpec
public class MyComponentSpec {
    @OnCreateLayout
    static ComponentLayout onCreateLayout(ComponentContext c) {
        return Column.create(c)
                .paddingDip(YogaEdge.ALL, 16)
                .child(Text.create(c)
                        .text("sup")
                        .textSizeSp(40))
                .child(Text.create(c)
                        .text("sup2")
                        .textSizeSp(20))
                .build();

    }
}

The annoation @LayoutSpec takes the class name minus Spec, thereby creating the MyComponent class via facebook’s annoation processor.

We create a Column using flexbox terminology, with two Text children, which are not TextViews incidentally.

Later tutorials will focus on using Android Views within Litho and events I should think.

android litho

Android: Style Toolbar/ActionBar and centre text

In recent support library updates, we have the Toolbar to use instead of the standard ActionBar to style via various properties in your style xml files.

You add this manually to your layout XML file.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  xmlns:tools="http://schemas.android.com/tools">
  <android.support.v7.widget.Toolbar
      android:id="@+id/toolbar"
      android:layout_alignParentTop="true"
      android:layout_width="match_parent"
      android:layout_height="?attr/actionBarSize"
      android:background="@color/toolbar_background"
      >
  ...

If you want to centre the title text, for example, you now just add a normal TextView and centre align it.

      <TextView
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:textColor="@color/toolbar_text"
          android:gravity="center"
          tools:text="Some title"
          android:id="@+id/toolbar_text"
          style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"/>

Obviously this is a lot to put at the top of every activity, you can instead place it in a separate layout file and use an include directive:

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <include android:id="@+id/toolbar_layout"
        layout="@layout/toolbar_layout" />
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/toolbar_layout">
...

In order to give this the title of your activity, you add this code in your onStart() method, or anywhere after the layout has been inflated:

TextView toolbarText = (TextView) findViewById(R.id.toolbar_text);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
if(toolbarText!=null && toolbar!=null) {
    toolbarText.setText(getTitle());
    setSupportActionBar(toolbar);
}

This will grab our toolbar, grab the text view which will hold our title, set the text on our text view and set the toolbar as our ActionBar.

Now when options menu etc, it will appear in that toolbar.

android android-toolbar

Android: Hiding the FAB and nested scroll events in CoordinatorLayout

The CoordinatorLayout helps you deal with nested scroll events from certain children, RecyclerView in our case.

If we place a RecyclerView and a FloatingActionBar in a CoordinatorLayout, we can tell the FAB to hide when we get a nested scroll event from the RecyclerView.

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/coord"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rec_view"
        android:background="@android:color/holo_green_dark"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical"
        >
    </android.support.v7.widget.RecyclerView>
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@android:drawable/star_big_on"
        app:layout_behavior="com.example.blar.myapplication.ScrollAwareFABBehavior"
        app:layout_anchorGravity="bottom|right|end"
        />
</android.support.design.widget.CoordinatorLayout

Note the FAB has app:layout_behavior pointing to a class. Let’s look at that now.

public class ScrollAwareFABBehavior extends CoordinatorLayout.Behavior<FloatingActionButton>  {
  public ScrollAwareFABBehavior(Context context, AttributeSet attrs) {
    super();
  }

  @Override
  public boolean onStartNestedScroll(final CoordinatorLayout coordinatorLayout, final FloatingActionButton child,
                                     final View directTargetChild, final View target, final int nestedScrollAxes) {
    return true;
  }

  @Override
  public void onNestedScroll(final CoordinatorLayout coordinatorLayout,
      final FloatingActionButton child,
      final View target, final int dxConsumed, final int dyConsumed,
      final int dxUnconsumed, final int dyUnconsumed) {
    super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed,dxUnconsumed, dyUnconsumed);
    if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {
      child.hide();
    } else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {
      child.show();
    }
  }
}

The first onStartNestedScroll method asks if we want to respond to a scroll event that happened in the CoordinatorLayout. We’re saying yes, but usually you say only on vertical scroll or what have you.

The the next onNestedScroll method, actually either hides or shows the FAB depending on the direction of scroll.

Each method have default implementations that return false and does nothing respectively.

android android-coordinatorlayout

Page 1 of 16
Next