Android GridView flip animation on each cell?

Harry117 picture Harry117 · Aug 27, 2013 · Viewed 8.5k times · Source

I am fairly new to android development and i'm creating a few simple applications for myself. I have ran into a problem in relation to animations, in particular a flip animation on each individual cell of a gridview when that cell is clicked.

What my application does so far is retrieves the contacts from the phone and displays the contact photo and the name in a gridview using an array adapter.

What i want to happen is when the user clicks on the grid cell of a contact it will perform a flip animation and display the contacts phone number on the back. When the user clicks on that cell again it will flip back to the previous view of the name and photo.

I have searched the internet and tried a few tutorials but none that have been of any great help, must of them infact confuse me, so if someone could help that would be great.

I'll post my current code below!

Thanks in advance.

This code is used to retrieve the information of the contacts!

package content;

import android.provider.MediaStore.Images;

public class ContactBean {
private String name;
private String phoneNo;
private String proPic;

public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
public String getPhoneNo() {
    return phoneNo;
}
public void setPhoneNo(String phoneNo) {
    this.phoneNo = phoneNo;
}

public String getProPic() {
    return proPic;
}

public void setProPic(String proPic) {
    this.proPic = proPic;
}

}

ViewContatcsActivity

package viewContacts;

import com.example.contactflipper.R;

import content.ContactBean;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.os.Bundle;

import android.provider.ContactsContract;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;


public class ViewContactsActivity extends Activity implements
OnItemClickListener {

private GridView listView;
private List<ContactBean> list = new ArrayList<ContactBean>();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.menu_viewcon_grid);

    listView = (GridView) findViewById(R.id.gridview);
    listView.setOnItemClickListener(this);
    String image_uri = ""; 
    Bitmap bitmap = null;

    Cursor phones = getContentResolver().query(
            ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,   null,
            null, null);
    while (phones.moveToNext()) {

        String name = phones
                .getString(phones
                        .getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));

        String phoneNumber = phones
                .getString(phones
                        .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

        image_uri = phones
                  .getString(phones
                        .getColumnIndex(ContactsContract.CommonDataKinds.Phone.PHOTO_URI));

        ContactBean objContact = new ContactBean();
        objContact.setName(name);

        objContact.setPhoneNo(phoneNumber);
        list.add(objContact);



    }
    phones.close();

    GridAdapter objAdapter = new GridAdapter(
            ViewContactsActivity.this, R.layout.card_front, list);
    listView.setAdapter(objAdapter);

    if (null != list && list.size() != 0) {
        Collections.sort(list, new Comparator<ContactBean>() {

            @Override
            public int compare(ContactBean lhs, ContactBean rhs) {
                return lhs.getName().compareTo(rhs.getName());
            }
        });
        AlertDialog alert = new AlertDialog.Builder(
                ViewContactsActivity.this).create();
        alert.setTitle("");

        alert.setMessage(list.size() + " Contact Found!!!");

        alert.setButton("OK", new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        alert.show();

    } else {
        showToast("No Contact Found!!!");
    }
}

private void showToast(String msg) {
    Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}

@Override
public void onItemClick(AdapterView<?> listview, View v, int position,
        long id) {
    ContactBean bean = (ContactBean) listview.getItemAtPosition(position);
    //implement something on the click of each listed item - bean
}

}

GridAdapter

package viewContacts;

import java.util.List;

import com.example.contactflipper.R;
import com.example.contactflipper.R.id;

import content.ContactBean;


import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class GridAdapter extends ArrayAdapter<ContactBean> {

    private Activity activity;
    private List<ContactBean> items;
    private int row;
    private ContactBean objBean;


    public GridAdapter(Activity act, int row, List<ContactBean> items) {
        super(act, row, items);

        this.activity = act;
        this.row = row;
        this.items = items;


    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        View view = convertView;
        ViewHolder holder;
        if (view == null) {
            LayoutInflater inflater = (LayoutInflater) activity
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(row, null);

            holder = new ViewHolder();
            view.setTag(holder);
        } else {
            holder = (ViewHolder) view.getTag();
        }

        if ((items == null) || ((position + 1) > items.size()))
            return view;

        objBean = items.get(position);

        holder.tvname = (TextView) view.findViewById(R.id.profileName);
        //holder.tvPhoneNo = (TextView) view.findViewById(R.id.tvphone);

        if (holder.tvname != null && null != objBean.getName()
                && objBean.getName().trim().length() > 0) {
            holder.tvname.setText(Html.fromHtml(objBean.getName()));
        }
        if (holder.tvPhoneNo != null && null != objBean.getPhoneNo()
                && objBean.getPhoneNo().trim().length() > 0) {
            holder.tvPhoneNo.setText(Html.fromHtml(objBean.getPhoneNo()));
        }
        if (holder.ivPic != null && null != objBean.getProPic()
                && objBean.getProPic().trim().length() > 0) {
            holder.ivPic.setBackground((Drawable) Html.fromHtml(objBean.getProPic()));
        }
        return view;
    }

    public class ViewHolder {
        public TextView tvname, tvPhoneNo;
        public ImageView ivPic;
    }

}

ViewContactsFragment

package viewContacts;

import com.example.contactflipper.R;
import com.example.contactflipper.R.id;
import com.example.contactflipper.R.layout;

import content.AppDetails;
import android.app.Activity;
import android.app.Fragment;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridView;

public class VCGridFragment extends Fragment {


    public static GridView mGridview;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){

            View view = inflater.inflate(R.layout.menu_viewcon_grid, container, false);
            Log.d("Called", "on Create View");
            return view;
        }

    //super.onCreateView(inflater, container, savedInstanceState);
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState){
        super.onViewCreated(view, savedInstanceState);
        Log.d("Called", "created Grid");
        mGridview = (GridView) view.findViewById(R.id.gridview);


        Configuration config = getResources().getConfiguration();

        if(AppDetails.isTablet){

            if(config.orientation == Configuration.ORIENTATION_LANDSCAPE){
                mGridview.setNumColumns(4);
            }else{
                mGridview.setNumColumns(3);
            }

        }else{
            if(config.orientation == Configuration.ORIENTATION_LANDSCAPE){
                mGridview.setNumColumns(3);
            }else{
                mGridview.setNumColumns(2);
            }
        }

        /*
        mGridview.setOnItemClickListener(new onItemClickLitener(){

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id){
                onGridItemClick((GridView) parent, view, position, id);
            }

        });
    }

    public void onGridItemClick(GridView g, View v, int position, long id){
        Activity activity = getActivity();
    }
    */
 }
}

GridView xml -

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/contact_grid"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    android:background="#ffffff"
    android:scrollbars="none"
    tools:context=".MainActivity" >

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:background="@drawable/gradient"
        android:padding="10dp" >

        <GridView
            android:id="@+id/gridview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginTop="50dp"
            android:numColumns="2"
            android:horizontalSpacing="8dp"
            android:scrollbars="none"
            android:verticalSpacing="8dp" >

        </GridView>

        <Button
            android:id="@+id/backButton"
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:layout_gravity="top|right"
            android:background="#8043BFC7"
            android:text="@string/edit_contacts"
            android:textColor="#ffffff"
            android:textStyle="bold" />

    </FrameLayout>

</RelativeLayout>

FRONT OF CARD XML -

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

    <ImageView
        android:id="@+id/profileThumb"
        android:layout_width="match_parent"
        android:layout_height="140dp"
        ></ImageView>

    <TextView
        android:id="@+id/profileName"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_gravity="bottom"
        android:background="#40000000"
        android:textColor="#ffffff"
        android:textSize="22sp">
        </TextView> 


</LinearLayout>

BACK OF CARD XML -

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="180dp"
    android:layout_height="180dp"
    android:orientation="vertical"
    android:background="#a6c"
    android:padding="10dp"
    android:gravity="bottom"
    >
    <TextView
        android:id="@+id/infoName"
        style="?android:textAppearanceLarge"
        android:textStyle="bold"
        android:textColor="#fff"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="HCKDAHOIW" 
        ></TextView>   

    <TextView
        android:id="@+id/infoLocality"
        style="?android:textAppearanceSmall"
        android:textAllCaps="true"
        android:textStyle="bold"
        android:textColor="#80ffffff"
        android:lineSpacingMultiplier="1.2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="convoy" 
        ></TextView>

    <TextView
        android:id="@+id/infoEmail"
        style="?android:textAppearanceSmall"
        android:textColor="#80ffffff"
        android:lineSpacingMultiplier="1.2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="[email protected]" 
        ></TextView>

    <TextView
        android:id="@+id/infoNumber"
        style="?android:textAppearanceSmall"
        android:textColor="#80ffffff"
        android:lineSpacingMultiplier="1.2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="(086) 123 4567" 
        ></TextView>

</LinearLayout>

Answer

Reid L Skipworth picture Reid L Skipworth · Aug 27, 2013

I would go about it something like this.

Let's say this is the layout you're going to inflate in your gridview and it's named view_flipper_layout. Of course you'd have to add all your textview components etc. to either the front or back linearlayout.

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

    <ViewFlipper
        android:id="@+id/my_view_flipper"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <LinearLayout
            android:id="@+id/front"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/back"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical" >

            <ImageView
                android:id="@+id/picture"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />

        </LinearLayout>

    </ViewFlipper>

</LinearLayout>

Now let's say this is the adapter

 public GridAdapter(Activity act, int row, List<ContactBean> items) {
    super(act, row, items);

    this.activity = act;
    this.row = row;
    this.items = items;


}


@Override
public View getView(final int position, View convertView, ViewGroup parent) {

    View view = convertView;
    ViewHolder holder;
    if (view == null) {
        LayoutInflater inflater = (LayoutInflater) activity
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        //here is where you inflate your layout containing your viewflipper
        view = inflater.inflate(R.layout.view_flipper_layout, null);

    } else {
        holder = (ViewHolder) view.getTag();
    }

    //reference the viewFlipper
    ViewFlipper flipper = (viewFlipper) holder.findViewById(R.id.my_view_flipper);
    //your front layout should be set to displayed be default 


    //now you can get get references to your textview or ImageViews contained within the layout
    TextView name = (TextView) holder.findViewById(R.id.name);
    name.setText("your text");

    ImageView picture = (ImageView) holder.findViewById(R.id.picture);

    //now you set your onclick and pass it the current viewflipper to control the displayed child
    flipper.setOnClickListener(new OnClickListener(){
        @Override
        public void onClick(View click) {

            flipViewFlipper(flipper);

        }

    });


    return view;
}


private void flipViewFlipper(ViewFlipper flipper){

   if(flipper.getDisplayedChild() == 0){
      flipper.setDisplayedChild(1);
   }
   else{
     flipper.setDisplayeChild(0);
   }

}

}

I'm typing this from my head, so just use it as a guide if you attempt to go this way.