viernes, 31 de enero de 2014

Android: Capitalize in layout

TextView

<TextView 
        android:textAllCaps="true"
/>

EditText

<EditText
        android:inputType="textCapWords"
/>

miércoles, 29 de enero de 2014

Android: Add and remove fragment from back stack

In this example the activity adds the fragment and the fragment removes itself.

Add to back stack

activity.getSupportFragmentManager().beginTransaction()
.replace(R.id.main_activity_content, userProfileFragment)
.addToBackStack(UserProfileFragment.BACK_STACK_NAME)
.commit();

Remove from back stack

getMainActivity().getSupportFragmentManager()
.popBackStackImmediate(UserProfileFragment.BACK_STACK_NAME,

FragmentManager.POP_BACK_STACK_INCLUSIVE);

viernes, 24 de enero de 2014

Android: Screen orientation

Code

Display display = ((WindowManager) getSystemService(WINDOW_SERVICE))
        .getDefaultDisplay();

int orientation = display.getRotation();

Usage

Display display = ((WindowManager) getSystemService(WINDOW_SERVICE))
        .getDefaultDisplay();

int orientation = display.getRotation();

if (orientation == Surface.ROTATION_90 || orientation == Surface.ROTATION_270) {
    // ...        
}

Android: Swipe gesture

OnSwipeTouchListener
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

public class OnSwipeTouchListener implements OnTouchListener {

    private final GestureDetector gestureDetector = 
        new GestureDetector(new GestureListener());

    public boolean onTouch(final View view, final MotionEvent motionEvent) {
        return gestureDetector.onTouchEvent(motionEvent);
    }

    private final class GestureListener extends SimpleOnGestureListener {

        private static final int SWIPE_THRESHOLD = 100;
        private static final int SWIPE_VELOCITY_THRESHOLD = 100;

        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, 
        float velocityX, float velocityY) {
            boolean result = false;
            try {
                float diffY = e2.getY() - e1.getY();
                float diffX = e2.getX() - e1.getX();
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    if (Math.abs(diffX) > SWIPE_THRESHOLD && 
                    Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffX > 0) {
                            onSwipeRight();
                        } else {
                            onSwipeLeft();
                        }
                    }
                } else {
                    if (Math.abs(diffY) > SWIPE_THRESHOLD && 
                    Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffY > 0) {
                            onSwipeBottom();
                        } else {
                            onSwipeTop();
                        }
                    }
                }
            } catch (Exception exception) {
                exception.printStackTrace();
            }
            return result;
        }
    }

    public void onSwipeRight() {
    }

    public void onSwipeLeft() {
    }

    public void onSwipeTop() {
    }

    public void onSwipeBottom() {
    }
}

Usage
view.setOnTouchListener(new OnSwipeTouchListener() {
    public void onSwipeTop() {
        Toast.makeText(MyActivity.this, "top", Toast.LENGTH_SHORT).show();
    }
    public void onSwipeRight() {
        Toast.makeText(MyActivity.this, "right", Toast.LENGTH_SHORT).show();
    }
    public void onSwipeLeft() {
        Toast.makeText(MyActivity.this, "left", Toast.LENGTH_SHORT).show();
    }
    public void onSwipeBottom() {
        Toast.makeText(MyActivity.this, "bottom", Toast.LENGTH_SHORT).show();
    }
});

jueves, 23 de enero de 2014

Android: Easy rounded edit text (Rounded background)

Layout

<EditText
        ...
        android:background="@drawable/rounded_edit_text"
        ... />

res/drawable

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >

    <corners
        android:bottomLeftRadius="3dp"
        android:bottomRightRadius="3dp"
        android:radius="5dp"
        android:topLeftRadius="3dp"
        android:topRightRadius="3dp" />
    <solid
        android:color="@android:color/white"/>

</shape>

jueves, 16 de enero de 2014

Android: No results grid view (same goes for list view)

Layout

The containing layout should be a RelativeLayout and the "no results" view should be above the grid view.

<RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <ImageView
            android:id="@+id/gridview_no_results"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="fitCenter"
            android:src="@drawable/background_no_results" />

        <GridView
            android:id="@+id/gridview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            ... />
</RelativeLayout>

Code

Set the empty view

@Override
 public void onViewCreated(View view, Bundle savedInstanceState) {
 
  super.onViewCreated(view, savedInstanceState);
  
  gridables = new ArrayList<CalendaredProgram>();
  gridView = (GridView) view.findViewById(R.id.gridview);
  
  ImageView noResultsView = (ImageView) view.findViewById(R.id.gridview_no_results);
  gridView.setEmptyView(noResultsView);
  
  this.setSearchButtonOnClickHandler();
 }

Do request

private class SearchTask
extends AsyncTask {

  ...

  @Override protected void onPostExecute(Response response) {
   
   // Assign empty list if there are no results
  }

  @Override
  protected TaskResult doInBackground(Params... params) {
   
   // Do request
  }
 }

miércoles, 15 de enero de 2014

Android: Singleton implementation

public class SingletonClass {
    private static class Holder {
        static final SingletonClass INSTANCE = new SingletonClass();
    }

    public static SingletonClass getInstance() {
        return Holder.INSTANCE;
    }

    // ...
}

miércoles, 8 de enero de 2014

Android: Get status bar height

public int getStatusBarHeight(Activity activity) {

Rect rectgle = new Rect();

Window window = activity.getWindow();
window.getDecorView().getWindowVisibleDisplayFrame(rectgle);

return rectgle.top;
}

Android: Obtaining the screen size


// Screen size, it includes the action bar in its calculation
// 
private static DisplayMetrics getScreenMetricsIncludingActionBar() {

  return Resources.getSystem().getDisplayMetrics();
}

// Screen size removing the action bar
// 
private static DisplayMetrics getScreenMetricsRemovingActionBar(
Activity activity) {

  DisplayMetrics metrics = new DisplayMetrics();
 activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);

  return metrics;

}

As a side note, the status bar height can be calculated like follows:
public static int getStatusBarHeight(Activity activity) {

 Rect rectgle = new Rect();
 Window window = activity.getWindow();
 window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
  
 return rectgle.top;
}

And the action bar height can be obtained like this:

XML:

?android:attr/actionBarSize

XML using ActionBarSherlock or AppCompat:

?attr/actionBarSize

Programatically:
final TypedArray styledAttributes = getContext().getTheme().obtainStyledAttributes(
                    new int[] { android.R.attr.actionBarSize });
mActionBarSize = (int) styledAttributes.getDimension(0, 0);

styledAttributes.recycle();

Android: Button with background and icon changing simultaneously

We will change the background in the style. I used a style since I had a lot of buttons whose background should behave the same. In each image view though we set its src to the corresponding selector.

<ImageView
            android:id="@+id/gallery_button"
            style="@style/ProgramDetailMenuItem"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:clickable="true"
            android:src="@drawable/galery_button_selector" />

res/drawable/galery_button_selector

<selector xmlns:android="http://schemas.android.com/apk/res/android" >
 
    <item        
android:drawable="@drawable/btn_galery_pressed"        
android:state_pressed="true"/>
    <item        
android:drawable="@drawable/btn_galery"        
android:state_enabled="true"/>

</selector>

Now we do the background color change.

res/values/styles

<resources xmlns:android="http://schemas.android.com/apk/res/android">

   ...
 
    <style name="ProgramDetailMenuItem">
       <item name="android:background">@drawable/program_detail_button_background</item>
    </style>

</resources>



res/drawable/program_detail_button_background



<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    
    <item android:drawable="@color/program_detail_button_pressed" android:state_pressed="true"/>
    <item android:drawable="@color/program_detail_button_not_pressed" android:state_enabled="true"/>

</selector>



res/values/colors



<?xml version="1.0" encoding="utf-8"?>
<resources>
    ...
    <color name="program_detail_button_pressed">#717171</color>
    <color name="program_detail_button_not_pressed">#00FFFFFF</color>
    
</resources>



The reason behind #00FFFFFF is that 00 is the alpha, and this value will set the alpha to 0 regardless of the following 6 hexa digits.

Android: Custom "toggle button"

We will use an ImageView as a toggle button. Having two states, a normal one and one when its pressed and an action when it is pressed.

<ImageView
        ...

        android:clickable="true"
        android:src="@drawable/favorite_button_selector"
        android:onClick="favoriteClicked" />

res/drawable

<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    
    <item android:drawable="@drawable/favorite_active" android:state_selected="true"/>
    <item android:drawable="@drawable/favorite_inactive" android:state_selected="false"/>

</selector>

To make this work though we need to explicitly call setSelected(boolean) somewhere in your class. The best place to do so is probably in the onClick handler (favoriteClicked in this case).

martes, 7 de enero de 2014

Android: Bold text

Programatically

TextView title = (TextView) convertView.findViewById(R.id.highlight_title);
title.setTypeface(null, Typeface.BOLD);
title.setText(calendaredProgram.getProgram().getTitle());

you can also do the following

Spanned fromHtml = Html.fromHtml("<b>Text</b>");
String text = fromHtml.toString();


In the view layout

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    ...

        <TextView
            android:id="@+id/highlight_title"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            ...
            android:text="@string/highlight_title"
            ... />

    ...

</RelativeLayout>
values/strings

<resources>

    ...
    <string name="highlight_title"><b>Some text</b></string>

</resources>


In the layout

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Alarm!"
    android:textSize="30sp"
    android:textStyle="bold" />