record swipe added
authordrizea <danielrizea27@gmail.com>
Sun, 15 Jul 2012 06:52:46 +0000 (09:52 +0300)
committerdrizea <danielrizea27@gmail.com>
Sun, 15 Jul 2012 06:52:46 +0000 (09:52 +0300)
record swipe added, record details moved in scroll view

12 files changed:
Open-ILS/src/Android/AndroidManifest.xml
Open-ILS/src/Android/res/layout/record_details_basic_fragment.xml
Open-ILS/src/Android/res/layout/record_details_more_fragment.xml [deleted file]
Open-ILS/src/Android/res/layout/simple_underlines.xml [new file with mode: 0644]
Open-ILS/src/Android/src/org/evergreen/android/searchCatalog/CopyInformation.java [new file with mode: 0644]
Open-ILS/src/Android/src/org/evergreen/android/searchCatalog/RecordDetails_Simple.java
Open-ILS/src/Android/src/org/evergreen/android/searchCatalog/SampleUnderlinesNoFade.java [new file with mode: 0644]
Open-ILS/src/Android/src/org/evergreen/android/searchCatalog/SearchCatalogListView.java
Open-ILS/src/Android/src/org/evergreen/android/searchCatalog/TabsView.java [deleted file]
Open-ILS/src/Android/src/org/evergreen/android/utils/ui/AdvancedDetailsFragment.java [deleted file]
Open-ILS/src/Android/src/org/evergreen/android/utils/ui/BasicDetailsFragment.java
Open-ILS/src/Android/src/org/evergreen/android/utils/ui/UnderlinePageIndicator.java [new file with mode: 0644]

index 357b319..e337a0d 100644 (file)
             android:label="Tabs/Styled"
             android:theme="@style/StyledIndicators"
             ></activity>  
+            
+        <activity android:name=".searchCatalog.SampleUnderlinesNoFade"
+            android:label="Underlines/No Fade"
+            >
+        </activity>
 
         <!-- Checkout Activities -->
         <activity android:name=".accountAccess.checkout.ItemsCheckOutListView"></activity>
index b12fd55..7bc52f2 100644 (file)
 <?xml version="1.0" encoding="utf-8"?>
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"   
- android:id="@+id/record_details_simple_view">
-<LinearLayout 
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/record_details_simple_view"
     android:layout_width="fill_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical">
-
-
-           <TextView  
-           xmlns:android="http://schemas.android.com/apk/res/android"
-           style="@style/sectionHeader"  
-           android:text="Basic Information"
-               /> 
-           
-           
-           <TextView 
-               style="@style/textLarge"
-           android:text="TITLE"   
-               />
-       
-            <TextView
-           android:id="@+id/record_details_simple_title"
-               style="@style/textSmall"
-           />
-           
-           <TextView  
-               style="@style/textLarge"
-           android:text="AUTHOR"   
-               />
-           
-           <TextView
-           android:id="@+id/record_details_simple_author"
-               style="@style/textSmall"   
-           />
-               
-           <TextView  
-               style="@style/textLarge"
-           android:text="PUBLISHER"   
-               />
-           
-           <TextView
-           android:id="@+id/record_details_simple_publisher"
-               style="@style/textSmall"   
-               />
-
-           
-          
-       </LinearLayout>
-</ScrollView>
\ No newline at end of file
+    android:layout_height="fill_parent"
+    android:orientation="vertical" >
+
+    <LinearLayout
+        android:layout_width="fill_parent"
+        android:layout_height="30dip"
+        android:background="@color/blue" >
+
+        <TextView
+            android:id="@+id/record_header_text"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:textSize="20sp" 
+            android:textColor="@color/white"
+            />
+    </LinearLayout>
+
+    <ScrollView
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent" >
+
+        <LinearLayout
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical" >
+
+            <TextView
+                xmlns:android="http://schemas.android.com/apk/res/android"
+                style="@style/sectionHeader"
+                android:text="Basic Information" />
+
+            <TextView
+                style="@style/textLarge"
+                android:text="TITLE" />
+
+            <TextView
+                android:id="@+id/record_details_simple_title"
+                style="@style/textSmall" />
+
+            <TextView
+                style="@style/textLarge"
+                android:text="AUTHOR" />
+
+            <TextView
+                android:id="@+id/record_details_simple_author"
+                style="@style/textSmall" />
+
+            <TextView
+                style="@style/textLarge"
+                android:text="PUBLISHER" />
+
+            <TextView
+                android:id="@+id/record_details_simple_publisher"
+                style="@style/textSmall" />
+
+            <TextView
+                xmlns:android="http://schemas.android.com/apk/res/android"
+                style="@style/sectionHeader"
+                android:text="Content" />
+
+            <TextView
+                style="@style/textLarge"
+                android:text="SUBJECT" />
+
+            <TextView
+                android:id="@+id/record_details_simple_subject"
+                style="@style/textSmall" />
+
+            <TextView
+                style="@style/textLarge"
+                android:text="SERIES" />
+
+            <TextView
+                android:id="@+id/record_details_simple_series"
+                style="@style/textSmall" />
+
+            <TextView
+                style="@style/textLarge"
+                android:text="SYNOPSIS" />
+
+            <TextView
+                android:id="@+id/record_details_simple_synopsis"
+                style="@style/textSmall" />
+
+            <TextView
+                xmlns:android="http://schemas.android.com/apk/res/android"
+                style="@style/sectionHeader"
+                android:text="Other" />
+
+            <TextView
+                style="@style/textLarge"
+                android:text="ISBN" />
+
+            <TextView
+                android:id="@+id/record_details_simple_isbn"
+                style="@style/textSmall" />
+        </LinearLayout>
+    </ScrollView>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/Open-ILS/src/Android/res/layout/record_details_more_fragment.xml b/Open-ILS/src/Android/res/layout/record_details_more_fragment.xml
deleted file mode 100644 (file)
index e2b2b6d..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"   
- android:id="@+id/record_details_simple_view">
-<LinearLayout 
-    android:layout_width="fill_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical">
-
-
-       <TextView  
-           xmlns:android="http://schemas.android.com/apk/res/android"
-           style="@style/sectionHeader"  
-           android:text="Content"
-               /> 
-           
-               
-                <TextView 
-               style="@style/textLarge"
-           android:text="SUBJECT"   
-               />
-       
-            <TextView
-           android:id="@+id/record_details_simple_subject"
-               style="@style/textSmall"
-           />
-           
-           <TextView  
-               style="@style/textLarge"
-           android:text="SERIES"   
-               />
-           
-           <TextView
-           android:id="@+id/record_details_simple_series"
-               style="@style/textSmall"   
-           />
-               
-           <TextView  
-               style="@style/textLarge"
-           android:text="SYNOPSIS"   
-               />
-           
-           <TextView
-           android:id="@+id/record_details_simple_synopsis"
-               style="@style/textSmall"   
-               />
-               
-               <TextView  
-           xmlns:android="http://schemas.android.com/apk/res/android"
-           style="@style/sectionHeader"  
-           android:text="Other"
-               /> 
-               
-                           <TextView  
-               style="@style/textLarge"
-           android:text="ISBN"   
-               />
-           
-           <TextView
-           android:id="@+id/record_details_simple_isbn"
-               style="@style/textSmall"   
-               />
-               
-               
-       </LinearLayout>
-</ScrollView>
\ No newline at end of file
diff --git a/Open-ILS/src/Android/res/layout/simple_underlines.xml b/Open-ILS/src/Android/res/layout/simple_underlines.xml
new file mode 100644 (file)
index 0000000..b53a392
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 Jake Wharton
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <android.support.v4.view.ViewPager
+        android:id="@+id/pager"
+        android:layout_width="fill_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        />
+    <org.evergreen.android.utils.ui.UnderlinePageIndicator
+        android:id="@+id/indicator"
+        android:layout_height="2dp"
+        android:layout_width="fill_parent"
+        />
+</LinearLayout>
\ No newline at end of file
diff --git a/Open-ILS/src/Android/src/org/evergreen/android/searchCatalog/CopyInformation.java b/Open-ILS/src/Android/src/org/evergreen/android/searchCatalog/CopyInformation.java
new file mode 100644 (file)
index 0000000..9b96807
--- /dev/null
@@ -0,0 +1,30 @@
+package org.evergreen.android.searchCatalog;
+
+import java.util.HashMap;
+import java.util.List;
+
+public class CopyInformation {
+
+       
+       public Integer org_id;
+       
+       public String call_number_sufix;
+       
+       public String copy_location;
+       
+       public HashMap<String,String> statuses;
+       
+       
+       public CopyInformation(List<String> list){
+               
+               
+               org_id = Integer.parseInt(list.get(0));
+               call_number_sufix = list.get(1);
+               copy_location = list.get(2);
+               
+               
+       }
+       
+       
+       
+}
index 9b7098c..3f6ba74 100644 (file)
@@ -22,8 +22,11 @@ public class RecordDetails_Simple extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
+               
                setContentView(R.layout.record_details_simple);
                
+               
+               
                titleTextView = (TextView) findViewById(R.id.record_details_simple_title);
                authorTextView = (TextView) findViewById(R.id.record_details_simple_author);
                publisherTextView = (TextView) findViewById(R.id.record_details_simple_publisher);
diff --git a/Open-ILS/src/Android/src/org/evergreen/android/searchCatalog/SampleUnderlinesNoFade.java b/Open-ILS/src/Android/src/org/evergreen/android/searchCatalog/SampleUnderlinesNoFade.java
new file mode 100644 (file)
index 0000000..c3151c3
--- /dev/null
@@ -0,0 +1,71 @@
+package org.evergreen.android.searchCatalog;
+
+import java.util.List;
+
+import org.evergreen.android.R;
+import org.evergreen.android.utils.ui.BaseSampleActivity;
+import org.evergreen.android.utils.ui.BasicDetailsFragment;
+import org.evergreen.android.utils.ui.TestFragmentAdapter;
+import org.evergreen.android.utils.ui.UnderlinePageIndicator;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.view.ViewPager;
+import android.widget.ListView;
+
+public class SampleUnderlinesNoFade extends BaseSampleActivity {
+    
+       
+       private RecordInfo record;
+       
+       private List<RecordInfo> records;
+       
+       
+       @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.simple_underlines);
+
+        
+        
+        records = (List<RecordInfo>)getIntent().getSerializableExtra("recordList");
+        
+        record = (RecordInfo) getIntent().getSerializableExtra("recordInfo");
+        
+        int record_position = getIntent().getIntExtra("recordPosition", 0);
+        mAdapter = new SearchFragmentAdapter(getSupportFragmentManager());
+
+        mPager = (ViewPager)findViewById(R.id.pager);
+        mPager.setAdapter(mAdapter);
+
+
+        mPager.setCurrentItem(record_position);
+        
+        UnderlinePageIndicator indicator = (UnderlinePageIndicator)findViewById(R.id.indicator);
+        indicator.setViewPager(mPager);
+        indicator.setFades(false);
+        mIndicator = indicator;
+    }
+    
+    class SearchFragmentAdapter extends TestFragmentAdapter {
+        public SearchFragmentAdapter(FragmentManager fm) {
+            super(fm);
+        }
+
+        @Override
+        public Fragment getItem(int position) {
+                       // position +1 for 1 - size values
+                       return BasicDetailsFragment.newInstance(records.get(position),position+1,records.size());
+               
+           
+        }
+
+        @Override
+        public int getCount() {
+            return records.size();
+               //return TabsView.CONTENT.length;
+        }
+
+    }
+}
\ No newline at end of file
index f997ba4..80c4117 100644 (file)
@@ -189,11 +189,14 @@ public class SearchCatalogListView extends Activity{
                        else{
                                //start activity with book details
                                
-                               Intent intent = new Intent(getBaseContext(),TabsView.class);
+                               Intent intent = new Intent(getBaseContext(),SampleUnderlinesNoFade.class);
                                //serialize object and pass it to next activity
                                intent.putExtra("recordInfo", info);
                                intent.putExtra("orgID",search.selectedOrganization.id);
                                intent.putExtra("depth",(search.selectedOrganization.level-1));
+                               
+                               intent.putExtra("recordList", searchResults);
+                               intent.putExtra("recordPosition", position);
                                startActivity(intent);
                        }
                }
@@ -215,7 +218,7 @@ public class SearchCatalogListView extends Activity{
                                progressDialog = new ProgressDialog(context);
                                
                                progressDialog.setMessage("Fetching data");
-                               //progressDialog.show();
+                               progressDialog.show();
                                
                                if(text.length()>0){
                                        
diff --git a/Open-ILS/src/Android/src/org/evergreen/android/searchCatalog/TabsView.java b/Open-ILS/src/Android/src/org/evergreen/android/searchCatalog/TabsView.java
deleted file mode 100644 (file)
index c458dd8..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.evergreen.android.searchCatalog;
-
-import org.evergreen.android.R;
-import org.evergreen.android.globals.NoAccessToServer;
-import org.evergreen.android.globals.NoNetworkAccessException;
-import org.evergreen.android.globals.Utils;
-import org.evergreen.android.utils.ui.AdvancedDetailsFragment;
-import org.evergreen.android.utils.ui.BaseSampleActivity;
-import org.evergreen.android.utils.ui.BasicDetailsFragment;
-import org.evergreen.android.utils.ui.TabPageIndicator;
-import org.evergreen.android.utils.ui.TestFragment;
-import org.evergreen.android.utils.ui.TestFragmentAdapter;
-
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.view.ViewPager;
-
-public class TabsView extends BaseSampleActivity {
-    private static final String[] CONTENT = new String[] { "Details", "Advanced"};
-
-    
-    private SearchCatalog search;
-    
-    private RecordInfo record;
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.simple_tabs);
-
-        record = (RecordInfo) getIntent().getSerializableExtra("recordInfo");
-               
-        Integer orgID = getIntent().getIntExtra("orgID", -1);
-        Integer orgDepth = getIntent().getIntExtra("depth", -1);
-        
-        mAdapter = new SearchFragmentAdapter(getSupportFragmentManager());
-
-        search = SearchCatalog.getInstance((ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE));    
-        
-        try {
-                       search.getLocationCount(record.doc_id, orgID, orgDepth);
-               } catch (NoNetworkAccessException e) {
-                       Utils.showNetworkNotAvailableDialog(this);
-               } catch (NoAccessToServer e) {
-                       Utils.showServerNotAvailableDialog(this);
-               }
-
-        //mAdapter.getItem(0).
-        
-        mPager = (ViewPager)findViewById(R.id.pager);
-        mPager.setAdapter(mAdapter);
-
-        mIndicator = (TabPageIndicator)findViewById(R.id.indicator);
-        mIndicator.setViewPager(mPager);
-    }
-
-    class SearchFragmentAdapter extends TestFragmentAdapter {
-        public SearchFragmentAdapter(FragmentManager fm) {
-            super(fm);
-        }
-
-        @Override
-        public Fragment getItem(int position) {
-               
-               if(position == 1)
-                       return AdvancedDetailsFragment.newInstance(record);
-               if(position == 0)
-                       return BasicDetailsFragment.newInstance(record);
-               
-            return TestFragment.newInstance(TabsView.CONTENT[position % TabsView.CONTENT.length]);
-        }
-
-        @Override
-        public int getCount() {
-            return 2;
-               //return TabsView.CONTENT.length;
-        }
-
-        @Override
-        public CharSequence getPageTitle(int position) {
-            return TabsView.CONTENT[position % TabsView.CONTENT.length].toUpperCase();
-        }
-    }
-}
diff --git a/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/AdvancedDetailsFragment.java b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/AdvancedDetailsFragment.java
deleted file mode 100644 (file)
index 1f26697..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-package org.evergreen.android.utils.ui;
-
-import org.evergreen.android.R;
-import org.evergreen.android.searchCatalog.RecordInfo;
-
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.LinearLayout;
-import android.widget.ScrollView;
-import android.widget.TextView;
-import android.widget.LinearLayout.LayoutParams;
-
-public class AdvancedDetailsFragment extends Fragment{
-
-       private RecordInfo record;
-       
-       private TextView seriesTextView;
-       private TextView subjectTextView;
-       private TextView synopsisTextView;
-       private TextView isbnTextView;
-       
-       
-       
-           public static AdvancedDetailsFragment newInstance(RecordInfo record) {
-               AdvancedDetailsFragment fragment = new AdvancedDetailsFragment(record);
-
-
-               return fragment;
-           }
-
-           public AdvancedDetailsFragment(RecordInfo record){
-               this.record = record;
-           }
-
-           @Override
-           public void onCreate(Bundle savedInstanceState) {
-               super.onCreate(savedInstanceState);
-
-           }
-
-           @Override
-           public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-           
-               ScrollView layout = (ScrollView) inflater.inflate(R.layout.record_details_more_fragment, null);
-
-                       seriesTextView = (TextView) layout.findViewById(R.id.record_details_simple_series);
-                       subjectTextView = (TextView) layout.findViewById(R.id.record_details_simple_subject);
-                       synopsisTextView = (TextView) layout.findViewById(R.id.record_details_simple_synopsis);
-                       isbnTextView = (TextView) layout.findViewById(R.id.record_details_simple_isbn);
-                       
-               
-                       seriesTextView.setText(record.series);
-                       subjectTextView.setText(record.subject);
-                       synopsisTextView.setText(record.synopsis);
-                       
-                       isbnTextView.setText(record.isbn);
-                       
-               return layout;
-           }
-
-           @Override
-           public void onSaveInstanceState(Bundle outState) {
-               super.onSaveInstanceState(outState);
-           }
-}
index a954425..bcbe9c8 100644 (file)
@@ -18,20 +18,34 @@ public class BasicDetailsFragment extends Fragment{
 
        
        private RecordInfo record;
+       private Integer position;
+       private Integer total;
+       
+       private TextView record_header;
        
        private TextView titleTextView;
        private TextView authorTextView;
        private TextView publisherTextView;
        
-           public static BasicDetailsFragment newInstance(RecordInfo record) {
-               BasicDetailsFragment fragment = new BasicDetailsFragment(record);
+       private TextView seriesTextView;
+       private TextView subjectTextView;
+       private TextView synopsisTextView;
+       private TextView isbnTextView;
+       
+       
+       
+           public static BasicDetailsFragment newInstance(RecordInfo record, Integer position, Integer total) {
+               BasicDetailsFragment fragment = new BasicDetailsFragment(record,position,total);
                
                return fragment;
            }
 
-           public BasicDetailsFragment(RecordInfo record){
+           public BasicDetailsFragment(RecordInfo record, Integer position, Integer total){
                
                this.record = record;
+               this.position = position;
+               this.total = total;
+               
            }
 
            @Override
@@ -43,18 +57,32 @@ public class BasicDetailsFragment extends Fragment{
            @Override
            public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            
-               ScrollView layout = (ScrollView) inflater.inflate(R.layout.record_details_basic_fragment, null);
+               LinearLayout layout = (LinearLayout) inflater.inflate(R.layout.record_details_basic_fragment, null);
 
+               record_header = (TextView) layout.findViewById(R.id.record_header_text);
+               
                titleTextView = (TextView) layout.findViewById(R.id.record_details_simple_title);
                        authorTextView = (TextView) layout.findViewById(R.id.record_details_simple_author);
                        publisherTextView = (TextView) layout.findViewById(R.id.record_details_simple_publisher);
                
+                       seriesTextView = (TextView) layout.findViewById(R.id.record_details_simple_series);
+                       subjectTextView = (TextView) layout.findViewById(R.id.record_details_simple_subject);
+                       synopsisTextView = (TextView) layout.findViewById(R.id.record_details_simple_synopsis);
+                       isbnTextView = (TextView) layout.findViewById(R.id.record_details_simple_isbn);
+                       
+                       record_header.setText("Record :" + position + " out of " + total  );
                        
                        titleTextView.setText(record.title);
                        authorTextView.setText(record.author);
                        publisherTextView.setText(record.pubdate + " " + record.publisher);
                        
-               
+                       seriesTextView.setText(record.series);
+                       subjectTextView.setText(record.subject);
+                       synopsisTextView.setText(record.synopsis);
+                       
+                       isbnTextView.setText(record.isbn);
+                       
+                       
                return layout;
            }
 
diff --git a/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/UnderlinePageIndicator.java b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/UnderlinePageIndicator.java
new file mode 100644 (file)
index 0000000..4e1839f
--- /dev/null
@@ -0,0 +1,378 @@
+package org.evergreen.android.utils.ui;
+
+import org.evergreen.android.R;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.support.v4.view.MotionEventCompat;
+import android.support.v4.view.ViewConfigurationCompat;
+import android.support.v4.view.ViewPager;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+
+/**
+ * Draws a line for each page. The current page line is colored differently
+ * than the unselected page lines.
+ */
+public class UnderlinePageIndicator extends View implements PageIndicator {
+    private static final int INVALID_POINTER = -1;
+    private static final int FADE_FRAME_MS = 30;
+
+    private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+
+    private boolean mFades;
+    private int mFadeDelay;
+    private int mFadeLength;
+    private int mFadeBy;
+
+    private ViewPager mViewPager;
+    private ViewPager.OnPageChangeListener mListener;
+    private int mScrollState;
+    private int mCurrentPage;
+    private float mPositionOffset;
+
+    private int mTouchSlop;
+    private float mLastMotionX = -1;
+    private int mActivePointerId = INVALID_POINTER;
+    private boolean mIsDragging;
+
+    private final Runnable mFadeRunnable = new Runnable() {
+      @Override public void run() {
+        final int alpha = Math.max(mPaint.getAlpha() - mFadeBy, 0);
+        mPaint.setAlpha(alpha);
+        invalidate();
+        if (alpha > 0) {
+          postDelayed(this, FADE_FRAME_MS);
+        }
+      }
+    };
+
+    public UnderlinePageIndicator(Context context) {
+        this(context, null);
+    }
+
+    public UnderlinePageIndicator(Context context, AttributeSet attrs) {
+        this(context, attrs, R.attr.vpiUnderlinePageIndicatorStyle);
+    }
+
+    public UnderlinePageIndicator(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        if (isInEditMode()) return;
+
+        final Resources res = getResources();
+
+        //Load defaults from resources
+        final boolean defaultFades = res.getBoolean(R.bool.default_underline_indicator_fades);
+        final int defaultFadeDelay = res.getInteger(R.integer.default_underline_indicator_fade_delay);
+        final int defaultFadeLength = res.getInteger(R.integer.default_underline_indicator_fade_length);
+        final int defaultSelectedColor = res.getColor(R.color.default_underline_indicator_selected_color);
+
+        //Retrieve styles attributes
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.UnderlinePageIndicator, defStyle, 0);
+
+        setFades(a.getBoolean(R.styleable.UnderlinePageIndicator_fades, defaultFades));
+        setSelectedColor(a.getColor(R.styleable.UnderlinePageIndicator_selectedColor, defaultSelectedColor));
+        setFadeDelay(a.getInteger(R.styleable.UnderlinePageIndicator_fadeDelay, defaultFadeDelay));
+        setFadeLength(a.getInteger(R.styleable.UnderlinePageIndicator_fadeLength, defaultFadeLength));
+
+        a.recycle();
+
+        final ViewConfiguration configuration = ViewConfiguration.get(context);
+        mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);
+    }
+
+    public boolean getFades() {
+        return mFades;
+    }
+
+    public void setFades(boolean fades) {
+        if (fades != mFades) {
+            mFades = fades;
+            if (fades) {
+                post(mFadeRunnable);
+            } else {
+                removeCallbacks(mFadeRunnable);
+                mPaint.setAlpha(0xFF);
+                invalidate();
+            }
+        }
+    }
+
+    public int getFadeDelay() {
+        return mFadeDelay;
+    }
+
+    public void setFadeDelay(int fadeDelay) {
+        mFadeDelay = fadeDelay;
+    }
+
+    public int getFadeLength() {
+        return mFadeLength;
+    }
+
+    public void setFadeLength(int fadeLength) {
+        mFadeLength = fadeLength;
+        mFadeBy = 0xFF / (mFadeLength / FADE_FRAME_MS);
+    }
+
+    public int getSelectedColor() {
+        return mPaint.getColor();
+    }
+
+    public void setSelectedColor(int selectedColor) {
+        mPaint.setColor(selectedColor);
+        invalidate();
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+
+        if (mViewPager == null) {
+            return;
+        }
+        final int count = mViewPager.getAdapter().getCount();
+        if (count == 0) {
+            return;
+        }
+
+        if (mCurrentPage >= count) {
+            setCurrentItem(count - 1);
+            return;
+        }
+
+        final int paddingLeft = getPaddingLeft();
+        final float pageWidth = (getWidth() - paddingLeft - getPaddingRight()) / (1f * count);
+        final float left = paddingLeft + pageWidth * (mCurrentPage + mPositionOffset);
+        final float right = left + pageWidth;
+        final float top = getPaddingTop();
+        final float bottom = getHeight() - getPaddingBottom();
+        canvas.drawRect(left, top, right, bottom, mPaint);
+    }
+
+    public boolean onTouchEvent(MotionEvent ev) {
+        if (super.onTouchEvent(ev)) {
+            return true;
+        }
+        if ((mViewPager == null) || (mViewPager.getAdapter().getCount() == 0)) {
+            return false;
+        }
+
+        final int action = ev.getAction();
+
+        switch (action & MotionEventCompat.ACTION_MASK) {
+            case MotionEvent.ACTION_DOWN:
+                mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
+                mLastMotionX = ev.getX();
+                break;
+
+            case MotionEvent.ACTION_MOVE: {
+                final int activePointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
+                final float x = MotionEventCompat.getX(ev, activePointerIndex);
+                final float deltaX = x - mLastMotionX;
+
+                if (!mIsDragging) {
+                    if (Math.abs(deltaX) > mTouchSlop) {
+                        mIsDragging = true;
+                    }
+                }
+
+                if (mIsDragging) {
+                    mLastMotionX = x;
+                    if (mViewPager.isFakeDragging() || mViewPager.beginFakeDrag()) {
+                        mViewPager.fakeDragBy(deltaX);
+                    }
+                }
+
+                break;
+            }
+
+            case MotionEvent.ACTION_CANCEL:
+            case MotionEvent.ACTION_UP:
+                if (!mIsDragging) {
+                    final int count = mViewPager.getAdapter().getCount();
+                    final int width = getWidth();
+                    final float halfWidth = width / 2f;
+                    final float sixthWidth = width / 6f;
+
+                    if ((mCurrentPage > 0) && (ev.getX() < halfWidth - sixthWidth)) {
+                        mViewPager.setCurrentItem(mCurrentPage - 1);
+                        return true;
+                    } else if ((mCurrentPage < count - 1) && (ev.getX() > halfWidth + sixthWidth)) {
+                        mViewPager.setCurrentItem(mCurrentPage + 1);
+                        return true;
+                    }
+                }
+
+                mIsDragging = false;
+                mActivePointerId = INVALID_POINTER;
+                if (mViewPager.isFakeDragging()) mViewPager.endFakeDrag();
+                break;
+
+            case MotionEventCompat.ACTION_POINTER_DOWN: {
+                final int index = MotionEventCompat.getActionIndex(ev);
+                final float x = MotionEventCompat.getX(ev, index);
+                mLastMotionX = x;
+                mActivePointerId = MotionEventCompat.getPointerId(ev, index);
+                break;
+            }
+
+            case MotionEventCompat.ACTION_POINTER_UP:
+                final int pointerIndex = MotionEventCompat.getActionIndex(ev);
+                final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
+                if (pointerId == mActivePointerId) {
+                    final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
+                    mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
+                }
+                mLastMotionX = MotionEventCompat.getX(ev, MotionEventCompat.findPointerIndex(ev, mActivePointerId));
+                break;
+        }
+
+        return true;
+    };
+
+    @Override
+    public void setViewPager(ViewPager viewPager) {
+        if (mViewPager == viewPager) {
+            return;
+        }
+        if (mViewPager != null) {
+            //Clear us from the old pager.
+            mViewPager.setOnPageChangeListener(null);
+        }
+        if (viewPager.getAdapter() == null) {
+            throw new IllegalStateException("ViewPager does not have adapter instance.");
+        }
+        mViewPager = viewPager;
+        mViewPager.setOnPageChangeListener(this);
+        invalidate();
+        post(new Runnable() {
+            @Override public void run() {
+                if (mFades) {
+                    post(mFadeRunnable);
+                }
+            }
+        });
+    }
+
+    @Override
+    public void setViewPager(ViewPager view, int initialPosition) {
+        setViewPager(view);
+        setCurrentItem(initialPosition);
+    }
+
+    @Override
+    public void setCurrentItem(int item) {
+        if (mViewPager == null) {
+            throw new IllegalStateException("ViewPager has not been bound.");
+        }
+        mViewPager.setCurrentItem(item);
+        mCurrentPage = item;
+        invalidate();
+    }
+
+    @Override
+    public void notifyDataSetChanged() {
+        invalidate();
+    }
+
+    @Override
+    public void onPageScrollStateChanged(int state) {
+        mScrollState = state;
+
+        if (mListener != null) {
+            mListener.onPageScrollStateChanged(state);
+        }
+    }
+
+    @Override
+    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+        mCurrentPage = position;
+        mPositionOffset = positionOffset;
+        if (mFades) {
+            if (positionOffsetPixels > 0) {
+                removeCallbacks(mFadeRunnable);
+                mPaint.setAlpha(0xFF);
+            } else if (mScrollState != ViewPager.SCROLL_STATE_DRAGGING) {
+                postDelayed(mFadeRunnable, mFadeDelay);
+            }
+        }
+        invalidate();
+
+        if (mListener != null) {
+            mListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
+        }
+    }
+
+    @Override
+    public void onPageSelected(int position) {
+        if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
+            mCurrentPage = position;
+            mPositionOffset = 0;
+            invalidate();
+            mFadeRunnable.run();
+        }
+        if (mListener != null) {
+            mListener.onPageSelected(position);
+        }
+    }
+
+    @Override
+    public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
+        mListener = listener;
+    }
+
+    @Override
+    public void onRestoreInstanceState(Parcelable state) {
+        SavedState savedState = (SavedState)state;
+        super.onRestoreInstanceState(savedState.getSuperState());
+        mCurrentPage = savedState.currentPage;
+        requestLayout();
+    }
+
+    @Override
+    public Parcelable onSaveInstanceState() {
+        Parcelable superState = super.onSaveInstanceState();
+        SavedState savedState = new SavedState(superState);
+        savedState.currentPage = mCurrentPage;
+        return savedState;
+    }
+
+    static class SavedState extends BaseSavedState {
+        int currentPage;
+
+        public SavedState(Parcelable superState) {
+            super(superState);
+        }
+
+        private SavedState(Parcel in) {
+            super(in);
+            currentPage = in.readInt();
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            super.writeToParcel(dest, flags);
+            dest.writeInt(currentPage);
+        }
+
+        public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
+            @Override
+            public SavedState createFromParcel(Parcel in) {
+                return new SavedState(in);
+            }
+
+            @Override
+            public SavedState[] newArray(int size) {
+                return new SavedState[size];
+            }
+        };
+    }
+}
\ No newline at end of file