jueves, 12 de diciembre de 2013

Android: TextView with hover / no-hover colors

TextColor

In this example I wanted to have my text change its color if the user was hovering over it.

Steps:

1 - Create a Selector resource file and place it in the res/drawables folder. Each item associates a color with a state. Android will make the drawable change for you.
2 - Create a TextView in the desired layout and set its "textColor" to the Selector resource file name.

Step 1:

res/color/enter_as_guest_selector.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@android:color/white" 
        android:state_pressed="true"/>
    <item android:color="@color/orange" 
        android:state_enabled="true"/>
</selector>

Step 2:

<TextView
        ...
        android:textColor="@color/enter_as_guest_selector"
        ... />


Background

res/values/colors.xml

<resources>
    <color name="white">#FFFFFF</drawable>
    <color  name="gray">#eaeaea</drawable>
</resources>

res/drawable/selector.xml

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

</selector>

Android: Making a button with hover / no hover images

In this example I wanted to make a custom Twitter button for my login page.

Steps:

1 - Create a Selector resource file and place it in the res/drawables folder. Each item associates an image with a state. Android will make the drawable changes for you.
2 - Create an ImageView in the desired layout and set its "src" to the Selector resource file name. Here you can also set the image's background. It depends on what you want to achieve.

Example:

Step 1:

res/drawables/register_button_selector.xml

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


Step 2:

<ImageView
        ...

        android:clickable="true"
        android:src="@drawable/register_button_selector"
        ... />

miércoles, 11 de diciembre de 2013

Android: Adding icons to the sides of a TextView

Have you ever struggled with having to place an icon relative to a TextView?
Before knowing this neat trick I would always add a new ImageView and play around until it would look ok. But there is an easy way. Just use drawableBottom, drawableTop, drawableLeft and drawableRight in your layout or setCompoundDrawablesWithIntrinsicBounds (int left, int top, int right, int bottom) to set it up programatically additionally you can set the padding to the images with drawablePadding in your layout file or setCompoundDrawablePadding (int amount).

Layout

Example:

<TextView
android:id="@+id/pending_friend_request_accept"
android:text="@string/yes"
...
android:drawableRight="@drawable/yes_image"
android:drawablePadding="4dp"
...
/>


Programatically

1)

Drawable img = getContext().getResources().getDrawable( R.drawable.yes_image );
img.setBounds( 0, 0, <width>, <height> );
textView.setCompoundDrawables( img, null, null, null );
textView.setCompoundDrawablePadding(<padding amount>);

2)

Drawable img = getContext().getResources().getDrawable( R.drawable.yes_image );
textView.setCompoundDrawablesWithIntrinsicBounds( img, null, null, null);
textView.setCompoundDrawablePadding(<padding amount>);

3)


textView.setCompoundDrawablesWithIntrinsicBounds( R.drawable.yes_image, 0, 0, 0);
textView.setCompoundDrawablePadding(<padding amount>);

martes, 10 de diciembre de 2013

Android: Style

For instance, you have the following:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
     >

    <EditText
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:paddingTop="10dp"
        android:paddingBottom="10dp"
        android:layout_marginLeft="2dp"
        android:layout_marginRight="2dp"
        android:background="@drawable/rounded_edit_text"

        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:hint="@string/username" />

    <EditText
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:paddingTop="10dp"
        android:paddingBottom="10dp"
        android:layout_marginLeft="2dp"
        android:layout_marginRight="2dp"
        android:background="@drawable/rounded_edit_text"

        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:hint="@string/password" />

     ...

</LinearLayout>

As you can see both EditTexts are intented to look the same. Wouldn't it be nice to have a "CSS class" feature in Android to apply the same style to both edit texts?. Thats exactly what you achieve with Style.

Steps:

1 - In the styles.xml file located in res/values folder. Add a new Style entry. In this entry you will have one item for each attribute you want the UI element to have. The Style name will be the name you will use to refer to this Style.
2 - In the element of your layout add a style attribute and sets its value as @style/<style name>.

Step 1:

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

    // Other styles
 
    <style name="LogInEditText">
        <item name="android:paddingLeft">10dp</item>
        <item name="android:paddingRight">10dp</item>
        <item name="android:paddingTop">10dp</item>
        <item name="android:paddingBottom">10dp</item>
        <item name="android:layout_marginLeft">2dp</item>
        <item name="android:layout_marginRight">2dp</item>
        <item name="android:background">@drawable/rounded_edit_text</item>
    </style>


</resources>



Step 2:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
     >

    <EditText
        style="@style/LogInEditText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:hint="@string/username" />

    <EditText
        style="@style/LogInEditText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:hint="@string/password" />

     ...

</LinearLayout>

domingo, 8 de diciembre de 2013

Android: Passing data to a fragment through its Arguments

To pass data to a fragment through its arguments you need to do the following steps:

1 - Create a Bundle object.
2 - Populate the Bundle object with the desired data. If the data to be passed is a custom class you need to make that class implement Parceable or pass all the data you need to recreate that object in the fragment (not recommended). See this post.
3 - Create the fragment and add the bundle object to the fragment's argument with the setArguments method. The first argument of this method is a key in the form of a String. Usually this key String will be a constant defined in the fragment class.
4 - In the fragment class in the onCreate method you need to take the bundle object from the arguments and what you please with it.

Example. Let's suppose I have a list of people and when the user clicks on one the Person object will be passed to a fragment for it to display.

public class Person implements Parcelable {
...

}

public class PeopleListActivity extends FragmentActivity {

private ListView list;
private FrameLayout fragmentContainer;

@Override
protected void onCreate(Bundle savedInstanceState) {

  super.onCreate(savedInstanceState);

  this.setContentView(R.layout.activity_people_list);

  fragmentContainer = 
    (FrameLayout) this.findViewById(R.id.fragment_container);

  PersonAdapter adapter = new PersonAdapter();

  list = (ListView) this.findViewById(R.id.listview);
  list.setAdapter(adapter);
  list.setOnClickListener(new OnClickListener() {

  @Override
  public void onClick(View v) {

    Bundle arguments = new Bundle();
    arguments.putParcelable(PersonDetailFragment.PERSON, person);

    PersonDetailFragment fragment = new PersonDetailFragment();

    fragment.setArguments(arguments);

    getSupportFragmentManager().beginTransaction()
      .add(R.id.fragment_container, fragment).commit();
  }
});

}


public class PersonDetailFragment extends Fragment {

public static final String PERSON =              
  "com.example.PersonList.PersonDetailFragment.PERSON";

...

@Override
public void onCreate(Bundle savedInstanceState) {
   
  super.onCreate(savedInstanceState);
        
  Parcelable person = (Person) this.getArguments().getParcelable(PERSON);
        
  ...
}

}

Android: Parcelable objects

You use parcelable classes to pass objects to activities and to fragments.
Implementing a parcelable class requires three simple steps:

1 - Make the class implement Parcelable
2 - Implement a constructor that receives a Parcel object and override writeToParcel method. One importante aspect to take into account at this step is that you have to read from the Parcel object in the same other your write to it.
3 - Create a custom Creator class that will create your Parcelable class. One

Lets do this:

import android.os.Parcel;
import android.os.Parcelable;

public class ParceableString implements Parcelable {

private String string;

...


public ParceableString(Parcel in){
    string = in.readString();
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(string);
}

@Override
public int describeContents(){
    return 0;
}


public static final Parcelable.Creator<ParceableString> CREATOR = new Parcelable.Creator<ParceableString>() {
   
        public ParceableString createFromParcel(Parcel in) {
            return new ParceableString(in);
        }

        public ParceableString[] newArray(int size) {
            return new ParceableString[size];
        }
    };

}


If your object contains other objects you would have to make those objects implement Parceable or persists its attributes as primitive types or other classes that are Parceable.

public class MyClass implements Parcelable {

private MyPoint myPoint;
private ParceableClass parceableObject;

public MyClass(Parcel in){
    myPoint = new MyPoint(in.readInt(), in.readInt());
    parceableObject = new ParceableClass(in);
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeInt(myPoint.x);
    dest.writeInt(myPoint.y);
    parceableObject.writeToParcel(dest, flags);
}

...
}

Save linear layout state

https://github.com/CharlesHarley/Example-Android-SavingInstanceState/blob/master/src/com/example/android/savinginstancestate/views/LockCombinationPicker.java