4

I've made a messaging app with a faux pop-up window (a normal activity with a transparent background) that displays any recieved sms's and you can 'flip' between any recieved texts (switch views) with a finger swipe left/right (to go previous/next), but ideally I want to control the animation with the users finger movement, so that (for example) if the user touches the screen and moves their finger left the view will flip/animate relative to as far as the users finger has moved. Also, if the animation reaches the halfway point and the user lifts their finger from the screen the animation will just finish and show the next view, and like i have seen in other applications if it hasn't reached the halfway point of the animation it will just return back to its original position.

There's 2 identical views in the view flipper (the one thats not in view loads the next/previous text depending on the users finger swipe direction) here's the xml for the layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:orientation="vertical"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          android:padding="20dp"
          >
          <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/outermost_layout"
          android:orientation="vertical"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          android:background="#364395"
          >
          <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/navbutton_layout"
          android:orientation="horizontal"
          android:layout_width="match_parent"
          android:gravity="center"
          android:layout_height="wrap_content"
          android:background="#364395"
          android:padding="10dp"
          >     
          <TextView android:text="" 
          android:id="@+id/previous_sms" 
          android:layout_width="100px" 
          android:layout_height="30px"
          android:background="#5E69AA"/>
          <TextView android:text="TextView" 
          android:id="@+id/sms_count" 
          android:layout_width="wrap_content" 
          android:layout_height="wrap_content"/>
          <TextView android:text="" 
          android:id="@+id/next_sms" 
          android:layout_width="100px" 
          android:layout_height="30px"
          android:background="#5E69AA"/>

                </LinearLayout>
          <ViewFlipper
           android:id="@+id/viewflipper"
           android:layout_width="fill_parent"
           android:layout_height="fill_parent">
            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/outer_layout"
          android:orientation="vertical"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:background="#364395"
          android:padding="10dp"
          android:gravity="center"
          >
            <TextView android:text="TextView" 
                      android:id="@+id/smspopup_title"
                      android:textColor="#FFF" 
                      android:layout_width="wrap_content" 
                      android:layout_height="55dp"
                      android:textSize="24dp"
                      />
              <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/body_layout"
              android:orientation="horizontal"
              android:layout_width="fill_parent"
              android:layout_height="150px"
              android:padding="10dp">
              <ScrollView android:id="@+id/scrollView1" 
                          android:layout_height="match_parent" 
                          android:layout_width="match_parent">
                        <TextView android:text="TextView" 
                                  android:id="@+id/smspopup_body" 
                                  android:textColor="#FFF"
                                  android:layout_width="wrap_content" 
                                  android:layout_height="wrap_content"
                                  android:textSize="18dp"
                                  />
              </ScrollView>
              </LinearLayout>
                      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                      android:id="@+id/button_layout"
                      android:orientation="horizontal"
                      android:layout_width="fill_parent"
                      android:layout_height="fill_parent"
                      android:gravity="center"                    
                      >
                        <Button android:text="Reply" 
                                android:id="@+id/reply_button" 
                                android:layout_width="wrap_content" 
                                android:layout_height="wrap_content" 
                                android:onClick="replyButtonHandler"
                                />
                        <Button android:text="Close" 
                                android:id="@+id/close_button" 
                                android:layout_width="wrap_content" 
                                android:layout_height="wrap_content" 
                                android:onClick="closeButtonHandler"
                                />
                    </LinearLayout>
        </LinearLayout>
        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/outer_layout2"
          android:orientation="vertical"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:background="#364395"
          android:padding="10dp"
          >
            <TextView android:text="TextView" 
                      android:id="@+id/smspopup_title2"
                      android:textColor="#FFF" 
                      android:layout_width="wrap_content" 
                      android:layout_height="55dp"
                      android:textSize="24dp"
                      />
              <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/body_layout2"
              android:orientation="horizontal"
              android:layout_width="fill_parent"
              android:layout_height="150px"
              android:padding="10dp">
              <ScrollView android:id="@+id/scrollView2" 
                          android:layout_height="match_parent" 
                          android:layout_width="match_parent">
                        <TextView android:text="TextView" 
                                  android:id="@+id/smspopup_body2" 
                                  android:textColor="#FFF"
                                  android:layout_width="wrap_content" 
                                  android:layout_height="wrap_content"
                                  android:textSize="18dp"
                                  />
              </ScrollView>
              </LinearLayout>
                      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                      android:id="@+id/button_layout2"
                      android:orientation="horizontal"
                      android:layout_width="fill_parent"
                      android:layout_height="fill_parent"
                      android:gravity="center"                    
                      >
                        <Button android:text="Reply" 
                                android:id="@+id/reply_button2" 
                                android:layout_width="wrap_content" 
                                android:layout_height="wrap_content" 
                                android:onClick="replyButtonHandler"
                                />
                        <Button android:text="Close" 
                                android:id="@+id/close_button2" 
                                android:layout_width="wrap_content" 
                                android:layout_height="wrap_content" 
                                android:onClick="closeButtonHandler"
                                />
                    </LinearLayout>
        </LinearLayout>
        </ViewFlipper>
        </LinearLayout>

And here's a code snippet for switching between the views:

public class SMSPopup extends Activity {
private NotificationManager mManager;



private static final int APP_ID = 0;
ViewFlipper viewFlipper;
 Animation animFlipInNext;
 Animation animFlipOutNext; 
 Animation animFlipInPrevious;
 Animation animFlipOutPrevious;
 boolean flipped = false;
String number ="";
String message = "";
Notification notification;
int messageCount = 0;
TextView messageCountDisplay;
TextView title;
TextView title2;
TextView bodyText;
TextView bodyText2;
TextView nextsms;
TextView prevsms;
int currentDisplayedSMS =0;
ArrayList<ArrayList<String>> arrayOfSMS ;
private float oldTouchValue;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.sms_popup);


    //2d array to hold our messages
    arrayOfSMS = new ArrayList<ArrayList<String>>();

    //viewflipper to switch between messages
    viewFlipper = (ViewFlipper)findViewById(R.id.viewflipper);
    //animations of switching between views
    animFlipInNext = AnimationUtils.loadAnimation(this, R.anim.flipinnext);
    animFlipOutNext = AnimationUtils.loadAnimation(this, R.anim.flipoutnext);
    animFlipInPrevious = AnimationUtils.loadAnimation(this, R.anim.flipinprevious);
    animFlipOutPrevious = AnimationUtils.loadAnimation(this, R.anim.flipoutprevious);

    //retrieve message
    Bundle extras = getIntent().getExtras();
    if(extras !=null)
    {
        number = extras.getString("number");
        message = extras.getString("message");
        //add to our array
        ArrayList<String> smsMessage = new ArrayList<String>();
        smsMessage.add(number);
        smsMessage.add(message);
        arrayOfSMS.add(smsMessage);
        currentDisplayedSMS = arrayOfSMS.indexOf(smsMessage);
        //set message count
        messageCount++;
        messageCountDisplay = (TextView) this.findViewById(R.id.sms_count);
        messageCountDisplay.setText("1/"+messageCount);
    }


    //set message into the textviews
   title = (TextView) this.findViewById(R.id.smspopup_title);
   title.setText("Message from "+fetchNameFromNumber(number));
   bodyText = (TextView) this.findViewById(R.id.smspopup_body);
   bodyText.setText(message);

   title2 = (TextView) findViewById(R.id.smspopup_title2);
   bodyText2 = (TextView) this.findViewById(R.id.smspopup_body2);
}

protected void onNewIntent(Intent intent)
{
    super.onNewIntent(intent);

    Bundle extras = intent.getExtras();
    if(extras !=null)
    {
        number = extras.getString("number");
        message = extras.getString("message");
        messageCount++;
        messageCountDisplay.setText("1/"+messageCount);
        //add to our array
        ArrayList<String> smsMessage = new ArrayList<String>();
        smsMessage.add(number);
        smsMessage.add(message);
        arrayOfSMS.add(smsMessage);
    }


}



public void setNextView()
{
    if(viewFlipper.getCurrentView().equals((View)findViewById(R.id.outer_layout)))
    {
        if(currentDisplayedSMS<messageCount)
        {
            currentDisplayedSMS++;
            if(currentDisplayedSMS>=messageCount)
            currentDisplayedSMS=messageCount-1; 
        }
        ArrayList<String> smsMessage = arrayOfSMS.get(currentDisplayedSMS);
        messageCountDisplay.setText((currentDisplayedSMS+1)+"/"+messageCount);
        title2.setText("Message from "+smsMessage.get(0));
           bodyText2.setText(smsMessage.get(1));  
    }
    else if(viewFlipper.getCurrentView().equals((View)findViewById(R.id.outer_layout2)))
    {
        if(currentDisplayedSMS<messageCount)
        {
            currentDisplayedSMS++;
            if(currentDisplayedSMS>=messageCount)
            currentDisplayedSMS=messageCount-1; 
        }
        ArrayList<String> smsMessage = arrayOfSMS.get(currentDisplayedSMS);
        messageCountDisplay.setText((currentDisplayedSMS+1)+"/"+messageCount);
        title.setText("Message from "+smsMessage.get(0));
           bodyText.setText(smsMessage.get(1));  
    }
}
public void setPreviousView()
{
    if(viewFlipper.getCurrentView().equals((View)findViewById(R.id.outer_layout)))
    {
        if(currentDisplayedSMS>0)
        {
            currentDisplayedSMS--;
            if(currentDisplayedSMS<=0)
            currentDisplayedSMS=0;  
        }
        ArrayList<String> smsMessage = arrayOfSMS.get(currentDisplayedSMS);
        messageCountDisplay.setText((currentDisplayedSMS+1)+"/"+messageCount);
        title2.setText("Message from "+smsMessage.get(0));
           bodyText2.setText(smsMessage.get(1));  
    }
    else if(viewFlipper.getCurrentView().equals((View)findViewById(R.id.outer_layout2)))
    {
        if(currentDisplayedSMS>0)
        {
            currentDisplayedSMS--;
            if(currentDisplayedSMS<=0)
            currentDisplayedSMS=0;  
        }
        ArrayList<String> smsMessage = arrayOfSMS.get(currentDisplayedSMS);
        messageCountDisplay.setText((currentDisplayedSMS+1)+"/"+messageCount);
        title.setText("Message from "+smsMessage.get(0));
           bodyText.setText(smsMessage.get(1));  
    }
}
public void removeCurrentSMS()
{
    ArrayList<String> smsMessage = arrayOfSMS.get(currentDisplayedSMS);        
    arrayOfSMS.remove(currentDisplayedSMS);
    //amend the current sms displayed 
    messageCount--;
    if(currentDisplayedSMS>0)
    {
        currentDisplayedSMS--;
    }
    else
    {
        currentDisplayedSMS= 0;
    }
    //get the new current message
    smsMessage = arrayOfSMS.get(currentDisplayedSMS);
    //amend the message count display
    messageCountDisplay.setText((currentDisplayedSMS+1)+"/"+messageCount);
    //amend the current view
    if(viewFlipper.getCurrentView().equals((View)findViewById(R.id.outer_layout)))
    {
        title.setText("Message from "+smsMessage.get(0));
        bodyText.setText(smsMessage.get(1));          
    }
    else if(viewFlipper.getCurrentView().equals((View)findViewById(R.id.outer_layout2)))
    {
        title2.setText("Message from "+smsMessage.get(0));
        bodyText2.setText(smsMessage.get(1));
    }
    messageCountDisplay.setText((currentDisplayedSMS+1)+"/"+messageCount);

}
public void replyButtonHandler(View v)
{
    ArrayList<String> smsMessage = arrayOfSMS.get(currentDisplayedSMS);
    Intent sendIntent;

    sendIntent = new Intent(Intent.ACTION_VIEW);         
        sendIntent.setData(Uri.parse("sms:"+smsMessage.get(0)));

    if(arrayOfSMS.size()==1)
    {
        finish();
    }
    else
    removeCurrentSMS();
  //sendIntent.putExtra("sms_body", "this is the body text"); 
    startActivity(sendIntent);
}
public void closeButtonHandler(View v)
{
    if(messageCount>1)
    removeCurrentSMS();
    else
    finish();
}

 @Override
    public boolean onTouchEvent(MotionEvent touchevent) {
     if(arrayOfSMS.size()<=1)
     {
         /*Toast.makeText(getBaseContext(), 
                 "Array too small - no sms to switch to", 
                 Toast.LENGTH_SHORT).show();*/
         return false;
     }
        switch (touchevent.getAction())
        {
            case MotionEvent.ACTION_DOWN:
            {
                oldTouchValue = touchevent.getX();
                break;
            }
            case MotionEvent.ACTION_UP:
            {
                float currentX = touchevent.getX();
                if (oldTouchValue < currentX)
                {
                    viewFlipper.setInAnimation(animFlipInNext);
                    viewFlipper.setOutAnimation(animFlipOutNext);
                    if(currentDisplayedSMS>0)
                    {
                        setPreviousView();
                      viewFlipper.showNext();
                    }
                }
                if (oldTouchValue > currentX)
                {
                    viewFlipper.setInAnimation(animFlipInPrevious);
                    viewFlipper.setOutAnimation(animFlipOutPrevious);
                    if(currentDisplayedSMS<messageCount-1)
                    {
                          setNextView();
                          viewFlipper.showPrevious();
                    }
                }

            break;
            }
        }
        return false;
    }


}

My animations are pretty simple - fliinnext.xml=

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/decelerate_interpolator">
<translate
 android:fromXDelta="-100%"
  android:toXDelta="0%"
 android:duration="500" />
</set>

flipoutnext.xml =

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/decelerate_interpolator">
<translate
 android:fromXDelta="0%"
 android:toXDelta="100%"
 android:duration="500" />
</set>

flipinprevious is the same as flipinnext but with android:fromXDelta="100%" and flipoutprevious is exactly the same as flipoutnext but with android:toXDelta="-100%"

Many thanks for your help in advance :)

AndroidNoob
  • 2,771
  • 2
  • 40
  • 53
  • 1
    They just added a `ViewPager` component to the Android Compatibility Library that may meet your requirements. – CommonsWare Jul 27 '11 at 12:50
  • Thanks for the pointer! Any links to a good tutorial on its use? – AndroidNoob Jul 27 '11 at 13:10
  • 1
    http://geekyouup.blogspot.com/2011/07/viewpager-example-from-paug.html – CommonsWare Jul 27 '11 at 16:01
  • Very helpful tutorial thanks for pointing me to that :) though the PagerAdapter for the ViewPager in the AwesomePager example only seems to be able to add a single view as a page (in the tutorial its a TextView) I'm trying to add a layout i've done in xml but i can't for the life of me work out how to! I tried looking at the example that came with the compatibility pack but I can't compile it I get errors everywhere :( how can I add a layout i've done (with multiple views/buttons) into the viewpager as a page? – AndroidNoob Jul 28 '11 at 11:15
  • EDIT: I am looking at the `instantiateItem(View collection, int position)`method, I've tried `View tv = (View)findViewById(R.layout.test_layout); ((ViewPager) collection).addView(tv,0);` but it just force closes with a null pointer exception (test_layout is an xml consisting of a linear layout with a textview, an imageview and a button) – AndroidNoob Jul 28 '11 at 11:24
  • I have not yet used `ViewPager` so I cannot comment. – CommonsWare Jul 28 '11 at 11:26
  • @CommonsWare no worries thanks very much for your help so far, I stumbled across another help article [here](http://stackoverflow.com/questions/6807262/get-focused-view-from-viewpager) and the OP uses a layout inflator to get the view, which works like a charm :) :`LayoutInflater layoutInflater = mActivity.getLayoutInflater();/*mActivity is the activity passed when the PagerAdapter is instanciated*/ View tv = layoutInflater.inflate(R.layout.test_layout, null); ((ViewPager) collection).addView(tv,0);` – AndroidNoob Jul 28 '11 at 11:35

0 Answers0