Walkthrough tutorial upon app launch
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 126 KiB |
|
After Width: | Height: | Size: 109 KiB |
|
After Width: | Height: | Size: 104 KiB |
|
After Width: | Height: | Size: 89 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 278 KiB |
@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!-- xmlns:app="http://schemas.android.com/apk/res/com.viewpagerindicator.sample" -->
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
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="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
/>
|
||||||
|
<com.viewpagerindicator.CirclePageIndicator
|
||||||
|
android:id="@+id/indicator"
|
||||||
|
android:padding="15dip"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_alignBottom="@id/pager"
|
||||||
|
android:background="#00000000"
|
||||||
|
style="@style/CustomCirclePageIndicator"
|
||||||
|
/>
|
||||||
|
<!--
|
||||||
|
app:radius="10dp"
|
||||||
|
app:fillColor="#FF888888"
|
||||||
|
app:strokeColor="#FF000000"
|
||||||
|
app:strokeWidth="2dp" -->
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
</LinearLayout>
|
||||||
@ -0,0 +1,101 @@
|
|||||||
|
<?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="fill_parent"
|
||||||
|
android:paddingLeft="4dip"
|
||||||
|
android:paddingRight="4dip"
|
||||||
|
android:background="@drawable/welcome_walkthrough_fabric"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/logo"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="110dip"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:paddingBottom="10dip"
|
||||||
|
android:layout_marginTop="30dip"
|
||||||
|
android:text="Connect now\nto get started!"
|
||||||
|
android:textColor="#444444"
|
||||||
|
android:textSize="40dip"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:shadowRadius="2"
|
||||||
|
android:shadowDy="1"
|
||||||
|
android:shadowColor="@android:color/white" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/error"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textColor="#ff0000"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="253dp"
|
||||||
|
android:paddingTop="5dip" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/login_later"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="45dip"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:paddingLeft="20dip"
|
||||||
|
android:paddingRight="20dip"
|
||||||
|
android:paddingBottom="5dip"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textColor="#ffffff" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/pw_login"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="45dip"
|
||||||
|
android:layout_above="@id/login_later"
|
||||||
|
android:paddingLeft="20dip"
|
||||||
|
android:paddingRight="20dip"
|
||||||
|
android:layout_marginLeft="15dip"
|
||||||
|
android:layout_marginRight="15dip"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:text="@string/welcome_login_pw"/>
|
||||||
|
|
||||||
|
<com.facebook.android.LoginButton
|
||||||
|
android:id="@+id/fb_login"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="45dip"
|
||||||
|
android:layout_above="@id/pw_login"
|
||||||
|
android:paddingLeft="20dip"
|
||||||
|
android:paddingRight="20dip"
|
||||||
|
android:layout_marginLeft="15dip"
|
||||||
|
android:layout_marginRight="15dip"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:drawableLeft="@drawable/facebook"
|
||||||
|
android:text="@string/actfm_ALA_fb_login" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/gg_login"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="45dip"
|
||||||
|
android:layout_above="@id/fb_login"
|
||||||
|
android:paddingLeft="20dip"
|
||||||
|
android:paddingRight="20dip"
|
||||||
|
android:layout_marginLeft="15dip"
|
||||||
|
android:layout_marginRight="15dip"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:drawableLeft="@drawable/google"
|
||||||
|
android:text="@string/actfm_ALA_gg_login" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tos"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="35dip"
|
||||||
|
android:layout_above="@id/gg_login"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="20dip"
|
||||||
|
android:paddingRight="20dip"
|
||||||
|
android:textSize="12.5sp"
|
||||||
|
android:textColor="#ffffff" />
|
||||||
|
</RelativeLayout>
|
||||||
|
</LinearLayout>
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
<?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="fill_parent"
|
||||||
|
android:orientation="vertical" >
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:orientation="vertical" >
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/welcome_walkthrough_fabric"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:src="@drawable/welcome_walkthrough_fabric" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/welcome_walkthrough_title"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_marginTop="27dp"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:text="Hello"
|
||||||
|
android:textColor="#444444"
|
||||||
|
android:textSize="40dip"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:shadowRadius="2"
|
||||||
|
android:shadowDy="1"
|
||||||
|
android:shadowColor="@android:color/white" />
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/welcome_walkthrough_image"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:src="@drawable/welcome_walkthrough_1" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/welcome_walkthrough_body"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_marginBottom="75dp"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:text="Hello"
|
||||||
|
android:textColor="#444444"
|
||||||
|
android:textSize="20dip"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:shadowRadius="2"
|
||||||
|
android:shadowDy="1"
|
||||||
|
android:shadowColor="@android:color/white" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@ -0,0 +1,125 @@
|
|||||||
|
package com.todoroo.astrid.welcome.tutorial;
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
import android.support.v4.view.PagerAdapter;
|
||||||
|
import android.support.v4.view.ViewPager;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.timsu.astrid.R;
|
||||||
|
|
||||||
|
public class ViewPagerAdapter extends PagerAdapter
|
||||||
|
{
|
||||||
|
private static int[] images = new int[]
|
||||||
|
{
|
||||||
|
R.drawable.welcome_walkthrough_1,
|
||||||
|
R.drawable.welcome_walkthrough_2,
|
||||||
|
R.drawable.welcome_walkthrough_3,
|
||||||
|
R.drawable.welcome_walkthrough_4,
|
||||||
|
R.drawable.welcome_walkthrough_5,
|
||||||
|
R.drawable.welcome_walkthrough_6,
|
||||||
|
R.drawable.welcome_screen
|
||||||
|
};
|
||||||
|
private static String[] title = new String[]
|
||||||
|
{
|
||||||
|
"Welcome to Astrid!",
|
||||||
|
"Make lists",
|
||||||
|
"Share lists",
|
||||||
|
"Divvy up tasks",
|
||||||
|
"Provide details",
|
||||||
|
"Discover",
|
||||||
|
"Login"
|
||||||
|
};
|
||||||
|
private static String[] body = new String[]
|
||||||
|
{
|
||||||
|
"The perfect personal\nto-do list that works great\nwith friends",
|
||||||
|
"Perfect for any list:\nto read, to watch, to buy,\nto visit, to do!",
|
||||||
|
"Share lists\nwith friends, housemates,\nor your sweetheart!",
|
||||||
|
"Never wonder who's\nbringing dessert!",
|
||||||
|
"Tap to add notes,\nset reminders,\nand much more!",
|
||||||
|
"Additional features,\nproductivity tips, and\nsuggestions from friends",
|
||||||
|
"Login"
|
||||||
|
};
|
||||||
|
private static int[] layouts = new int[]
|
||||||
|
{
|
||||||
|
R.layout.welcome_walkthrough_page,
|
||||||
|
R.layout.welcome_walkthrough_page,
|
||||||
|
R.layout.welcome_walkthrough_page,
|
||||||
|
R.layout.welcome_walkthrough_page,
|
||||||
|
R.layout.welcome_walkthrough_page,
|
||||||
|
R.layout.welcome_walkthrough_page,
|
||||||
|
R.layout.welcome_walkthrough_login_page,
|
||||||
|
|
||||||
|
};
|
||||||
|
private final Context context;
|
||||||
|
public WelcomeWalkthrough parent;
|
||||||
|
|
||||||
|
public ViewPagerAdapter( Context context )
|
||||||
|
{
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount()
|
||||||
|
{
|
||||||
|
return layouts.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object instantiateItem( View pager, int position )
|
||||||
|
{
|
||||||
|
LayoutInflater inflater = LayoutInflater.from(context);
|
||||||
|
|
||||||
|
View pageView = inflater.inflate(layouts[position], null, true);
|
||||||
|
pageView.setLayoutParams( new ViewGroup.LayoutParams(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT));
|
||||||
|
|
||||||
|
if (position != getCount()-1){
|
||||||
|
ImageView imageView = (ImageView) pageView.findViewById(R.id.welcome_walkthrough_image);
|
||||||
|
imageView.setImageResource(images[position]);
|
||||||
|
ImageView fabricImage = (ImageView) pageView.findViewById(R.id.welcome_walkthrough_fabric);
|
||||||
|
fabricImage.setScaleType(ImageView.ScaleType.FIT_XY);
|
||||||
|
|
||||||
|
TextView titleView = (TextView) pageView.findViewById(R.id.welcome_walkthrough_title);
|
||||||
|
titleView.setText(title[position]);
|
||||||
|
TextView bodyView = (TextView) pageView.findViewById(R.id.welcome_walkthrough_body);
|
||||||
|
bodyView.setText(body[position]);
|
||||||
|
}
|
||||||
|
|
||||||
|
((ViewPager)pager).addView( pageView, 0 );
|
||||||
|
parent.pageScrolled(position, pageView);
|
||||||
|
return pageView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroyItem( View pager, int position, Object view )
|
||||||
|
{
|
||||||
|
((ViewPager)pager).removeView( (View)view );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isViewFromObject( View view, Object object )
|
||||||
|
{
|
||||||
|
return view.equals( object );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finishUpdate( View view ) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreState( Parcelable p, ClassLoader c ) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Parcelable saveState() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startUpdate( View view ) {}
|
||||||
|
}
|
||||||
@ -0,0 +1,178 @@
|
|||||||
|
|
||||||
|
package com.todoroo.astrid.welcome.tutorial;
|
||||||
|
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.view.ViewPager;
|
||||||
|
import android.text.SpannableString;
|
||||||
|
import android.text.Spanned;
|
||||||
|
import android.text.TextPaint;
|
||||||
|
import android.text.style.ClickableSpan;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
|
import android.view.Window;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.timsu.astrid.R;
|
||||||
|
import com.todoroo.andlib.utility.DialogUtilities;
|
||||||
|
import com.todoroo.astrid.actfm.ActFmLoginActivity;
|
||||||
|
import com.todoroo.astrid.activity.Eula;
|
||||||
|
import com.todoroo.astrid.welcome.WelcomeLogin;
|
||||||
|
import com.viewpagerindicator.CirclePageIndicator;
|
||||||
|
import com.viewpagerindicator.PageIndicator;
|
||||||
|
|
||||||
|
public class WelcomeWalkthrough extends ActFmLoginActivity {
|
||||||
|
ViewPager mPager;
|
||||||
|
ViewPagerAdapter mAdapter;
|
||||||
|
PageIndicator mIndicator;
|
||||||
|
View currentView;
|
||||||
|
int currentPage;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
//setContentView(R.layout.welcome_walkthrough);
|
||||||
|
|
||||||
|
mAdapter = new ViewPagerAdapter(this);
|
||||||
|
mAdapter.parent = this;
|
||||||
|
|
||||||
|
mPager = (ViewPager)findViewById(R.id.pager);
|
||||||
|
mPager.setAdapter(mAdapter);
|
||||||
|
|
||||||
|
mIndicator = (CirclePageIndicator)findViewById(R.id.indicator);
|
||||||
|
mIndicator.setViewPager(mPager);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected int getContentViewResource() {
|
||||||
|
return R.layout.welcome_walkthrough;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getTitleResource() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
public void pageScrolled(int position, View view){
|
||||||
|
Log.d(null, "Updated ui");
|
||||||
|
currentView = view;
|
||||||
|
currentPage = position;
|
||||||
|
if (position == mAdapter.getCount()-1) {
|
||||||
|
initializeUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initializeUI() {
|
||||||
|
if(mAdapter == null)
|
||||||
|
return;
|
||||||
|
if(currentPage == mAdapter.getCount()-1){
|
||||||
|
super.initializeUI();
|
||||||
|
setupTermsOfService();
|
||||||
|
setupLoginLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SpannableString getLinkStringWithCustomInterval(String base, String linkComponent,
|
||||||
|
int start, int endOffset, final OnClickListener listener) {
|
||||||
|
SpannableString link = new SpannableString (String.format("%s %s", //$NON-NLS-1$
|
||||||
|
base, linkComponent));
|
||||||
|
ClickableSpan linkSpan = new ClickableSpan() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View widget) {
|
||||||
|
listener.onClick(widget);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void updateDrawState(TextPaint ds) {
|
||||||
|
ds.setUnderlineText(true);
|
||||||
|
ds.setColor(Color.rgb(255, 255, 255));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
link.setSpan(linkSpan, start, link.length() + endOffset, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
protected void setupTermsOfService() {
|
||||||
|
TextView tos = (TextView)currentView.findViewById(R.id.tos);
|
||||||
|
tos.setOnClickListener(showTosListener);
|
||||||
|
|
||||||
|
String tosBase = getString(R.string.welcome_login_tos_base);
|
||||||
|
String tosLink = getString(R.string.welcome_login_tos_link);
|
||||||
|
SpannableString link = getLinkStringWithCustomInterval(tosBase, tosLink, tosBase.length() + 2, -1, showTosListener);
|
||||||
|
tos.setText(link);
|
||||||
|
}
|
||||||
|
protected void setupPWLogin() {
|
||||||
|
Button pwLogin = (Button) findViewById(R.id.pw_login);
|
||||||
|
pwLogin.setOnClickListener(signUpListener);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
protected void setupWalkthroughLogin() {
|
||||||
|
Button loginButton = (Button)currentView.findViewById(R.id.walkthrough_login);
|
||||||
|
loginButton.setOnClickListener(showWalkthroughLoginListener);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
protected void setupLoginLater() {
|
||||||
|
TextView loginLater = (TextView)currentView.findViewById(R.id.login_later);
|
||||||
|
loginLater.setOnClickListener(loginLaterListener);
|
||||||
|
String loginLaterBase = getString(R.string.welcome_login_later);
|
||||||
|
SpannableString loginLaterLink = new SpannableString(String.format("%s", loginLaterBase)); //$NON-NLS-1$
|
||||||
|
ClickableSpan laterSpan = new ClickableSpan() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View widget) {
|
||||||
|
loginLaterListener.onClick(widget);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void updateDrawState(TextPaint ds) {
|
||||||
|
ds.setUnderlineText(true);
|
||||||
|
ds.setColor(Color.rgb(255, 255, 255));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
loginLaterLink.setSpan(laterSpan, 0, loginLaterBase.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
loginLater.setText(loginLaterLink);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final OnClickListener showTosListener = new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Eula.showEulaBasic(WelcomeWalkthrough.this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private void showWelcomeLoginActivty() {
|
||||||
|
Intent showWelcomeLogin = new Intent(this, WelcomeLogin.class);
|
||||||
|
showWelcomeLogin.putExtra(ActFmLoginActivity.SHOW_TOAST, false);
|
||||||
|
startActivity(showWelcomeLogin);
|
||||||
|
}
|
||||||
|
protected final OnClickListener showWalkthroughLoginListener = new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
showWelcomeLoginActivty();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
protected final OnClickListener loginLaterListener = new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View arg0) {
|
||||||
|
String title = getString(R.string.welcome_login_confirm_later_title);
|
||||||
|
String confirmLater = getString(R.string.welcome_login_confirm_later_dialog);
|
||||||
|
DialogUtilities.okCancelCustomDialog(WelcomeWalkthrough.this, title, confirmLater,
|
||||||
|
R.string.welcome_login_confirm_later_ok,
|
||||||
|
R.string.welcome_login_confirm_later_cancel,
|
||||||
|
android.R.drawable.ic_dialog_alert,
|
||||||
|
null, confirmLaterListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final DialogInterface.OnClickListener confirmLaterListener = new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
#Android generated
|
||||||
|
bin
|
||||||
|
gen
|
||||||
|
|
||||||
|
#Eclipse
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.settings
|
||||||
|
|
||||||
|
#IntelliJ IDEA
|
||||||
|
.idea
|
||||||
|
*.iml
|
||||||
|
|
||||||
|
#Maven
|
||||||
|
target
|
||||||
|
release.properties
|
||||||
|
pom.xml.*
|
||||||
@ -0,0 +1,88 @@
|
|||||||
|
Change Log
|
||||||
|
==========
|
||||||
|
|
||||||
|
Version 2.2.2 *(2011-12-31)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* Fix incorrect `R.java` imports in all of the sample activities.
|
||||||
|
|
||||||
|
|
||||||
|
Version 2.2.1 *(2011-12-31)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* New `setTypeface(Typeface)` and `getTypeface()` methods for title indicator.
|
||||||
|
(Thanks Dimitri Fedorov)
|
||||||
|
* Added styled tab indicator sample.
|
||||||
|
* Support for widths other than those that could be measured exactly.
|
||||||
|
|
||||||
|
|
||||||
|
Version 2.2.0 *(2011-12-13)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* Default title indicator style is now 'underline'.
|
||||||
|
* Title indicator now allows specifying an `OnCenterItemClickListener` which
|
||||||
|
will give you callbacks when the current item title has been clicked.
|
||||||
|
(Thanks Chris Banes)
|
||||||
|
|
||||||
|
|
||||||
|
Version 2.1.0 *(2011-11-30)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* Indicators now have a `notifyDataSetChanged` method which should be called
|
||||||
|
when changes are made to the adapter.
|
||||||
|
* Fix: Avoid `NullPointerException`s when the `ViewPager` is not immediately
|
||||||
|
bound to the indicator.
|
||||||
|
|
||||||
|
|
||||||
|
Version 2.0.0 *(2011-11-20)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* New `TabPageIndicator`! Uses the Ice Cream Sandwich-style action bar tabs
|
||||||
|
which fill the width of the view when there are only a few tabs or provide
|
||||||
|
horizontal animated scrolling when there are many.
|
||||||
|
* Update to link against ACLv4r4. This will now be required in all implementing
|
||||||
|
applications.
|
||||||
|
* Allow dragging the title and circle indicators to drag the pager.
|
||||||
|
* Remove orientation example as the DirectionalViewPager library has not been
|
||||||
|
updated to ACLv4r4.
|
||||||
|
|
||||||
|
|
||||||
|
Version 1.2.1 *(2011-10-20)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Maven 3 is now required when building from the command line.
|
||||||
|
|
||||||
|
* Update to support ADT 14.
|
||||||
|
|
||||||
|
|
||||||
|
Version 1.2.0 *(2011-10-04)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* Move to `com.viewpagerindicator` package.
|
||||||
|
* Move maven group and artifact to `com.viewpagerindicator:library`.
|
||||||
|
|
||||||
|
|
||||||
|
Version 1.1.0 *(2011-10-02)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* Package changed from `com.jakewharton.android.viewpagerindicator` to
|
||||||
|
`com.jakewharton.android.view`.
|
||||||
|
* Add vertical orientation support to the circle indicator.
|
||||||
|
* Fix: Corrected drawing bug where a single frame would be drawn as if the
|
||||||
|
pager had completed its scroll when in fact it was still scrolling.
|
||||||
|
(Thanks SimonVT!)
|
||||||
|
|
||||||
|
|
||||||
|
Version 1.0.1 *(2011-09-15)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* Fade selected title color to normal text color during the swipe to and from
|
||||||
|
the center position.
|
||||||
|
* Fix: Ensure both the indicator and footer line are updated when changing the
|
||||||
|
footer color via the `setFooterColor` method.
|
||||||
|
|
||||||
|
|
||||||
|
Version 1.0.0 *(2011-08-07)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Initial release.
|
||||||
@ -0,0 +1,152 @@
|
|||||||
|
Android ViewPagerIndicator
|
||||||
|
==========================
|
||||||
|
|
||||||
|
Port of [Patrik Åkerfeldt][1]'s paging indicators that are compatible with the
|
||||||
|
ViewPager from the [Android Compatibility Library][2] and
|
||||||
|
[ActionBarSherlock][3].
|
||||||
|
|
||||||
|
Try out the sample application [on the Android Market][10].
|
||||||
|
|
||||||
|
![ViewPagerIndicator Sample Screenshots][9]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Usage
|
||||||
|
=====
|
||||||
|
|
||||||
|
*For a working implementation of this project see the `sample/` folder.*
|
||||||
|
|
||||||
|
1. Include one of the widgets in your view. This should usually be placed
|
||||||
|
adjacent to the `ViewPager` it represents.
|
||||||
|
|
||||||
|
<com.viewpagerindicator.TitlePageIndicator
|
||||||
|
android:id="@+id/titles"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="fill_parent" />
|
||||||
|
|
||||||
|
2. In your `onCreate` method (or `onCreateView` for a fragment), bind the
|
||||||
|
indicator to the `ViewPager`.
|
||||||
|
|
||||||
|
//Set the pager with an adapter
|
||||||
|
ViewPager pager = (ViewPager)findViewById(R.id.pager);
|
||||||
|
pager.setAdapter(new TestAdapter(getSupportFragmentManager()));
|
||||||
|
|
||||||
|
//Bind the title indicator to the adapter
|
||||||
|
TitlePageIndicator titleIndicator = (TitlePageIndicator)findViewById(R.id.titles);
|
||||||
|
titleIndicator.setViewPager(pager);
|
||||||
|
|
||||||
|
*Note*: If you are using `TitlePageIndicator` your adapter must implement
|
||||||
|
`TitleProvider`.
|
||||||
|
|
||||||
|
3. *(Optional)* If you use an `OnPageChangeListener` with your view pager
|
||||||
|
you should set it in the indicator rather than on the pager directly.
|
||||||
|
|
||||||
|
//continued from above
|
||||||
|
titleIndicator.setOnPageChangeListener(mPageChangeListener);
|
||||||
|
|
||||||
|
|
||||||
|
Theming
|
||||||
|
-------
|
||||||
|
|
||||||
|
There are three ways to style the look of the indicators.
|
||||||
|
|
||||||
|
1. **Theme XML**. An attribute for each type of indicator is provided in which
|
||||||
|
you can specify a custom style.
|
||||||
|
2. **Layout XML**. Through the use of a custom namespace you can include any
|
||||||
|
desired styles.
|
||||||
|
3. **Object methods**. Both styles have getters and setters for each style
|
||||||
|
attribute which can be changed at any point.
|
||||||
|
|
||||||
|
Each indicator has a demo which creates the same look using each of these
|
||||||
|
methods.
|
||||||
|
|
||||||
|
|
||||||
|
Including In Your Project
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Android-ViewPagerIndicator is presented as an [Android library project][7]. A
|
||||||
|
standalone JAR is not possible due to the theming capabilities offered by the
|
||||||
|
indicator widgets.
|
||||||
|
|
||||||
|
You can include this project by [referencing it as a library project][8] in
|
||||||
|
Eclipse or ant.
|
||||||
|
|
||||||
|
If you are a Maven user you can easily include the library by specifying it as
|
||||||
|
a dependency:
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.viewpagerindicator</groupId>
|
||||||
|
<artifactId>library</artifactId>
|
||||||
|
<version>2.2.2</version>
|
||||||
|
<type>apklib</type>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
You must also include the following repository:
|
||||||
|
|
||||||
|
<repository>
|
||||||
|
<id>com.jakewharton</id>
|
||||||
|
<url>http://r.jakewharton.com/maven/release</url>
|
||||||
|
</repository>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
This project depends on the `ViewPager` class which is available in the
|
||||||
|
[Android Compatibility Library][2] or [ActionBarSherlock][3]. Details for
|
||||||
|
including one of those libraries is available on their respecitve web sites.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Developed By
|
||||||
|
============
|
||||||
|
|
||||||
|
* Jake Wharton - <jakewharton@gmail.com>
|
||||||
|
|
||||||
|
|
||||||
|
Credits
|
||||||
|
-------
|
||||||
|
|
||||||
|
* [Patrik Åkerfeldt][1] - Author of [ViewFlow][4], a precursor to the ViewPager,
|
||||||
|
which supports paged views and is the original source of both the title
|
||||||
|
and circle indicators.
|
||||||
|
* [Francisco Figueiredo Jr.][5] - Idea and [first implementation][6] for
|
||||||
|
fragment support via ViewPager.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
License
|
||||||
|
=======
|
||||||
|
|
||||||
|
Copyright 2011 Patrik Åkerfeldt
|
||||||
|
Copyright 2011 Francisco Figueiredo Jr.
|
||||||
|
Copyright 2011 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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[1]: https://github.com/pakerfeldt
|
||||||
|
[2]: http://developer.android.com/sdk/compatibility-library.html
|
||||||
|
[3]: http://actionbarsherlock.com
|
||||||
|
[4]: https://github.com/pakerfeldt/android-viewflow
|
||||||
|
[5]: https://github.com/franciscojunior
|
||||||
|
[6]: https://gist.github.com/1122947
|
||||||
|
[7]: http://developer.android.com/guide/developing/projects/projects-eclipse.html
|
||||||
|
[8]: http://developer.android.com/guide/developing/projects/projects-eclipse.html#ReferencingLibraryProject
|
||||||
|
[9]: https://raw.github.com/JakeWharton/Android-ViewPagerIndicator/master/sample/screens.png
|
||||||
|
[10]: https://market.android.com/details?id=com.viewpagerindicator.sample
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.viewpagerindicator"
|
||||||
|
android:versionCode="26"
|
||||||
|
android:versionName="2.2.2">
|
||||||
|
|
||||||
|
<uses-sdk android:minSdkVersion="4" />
|
||||||
|
</manifest>
|
||||||
@ -0,0 +1,85 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project name="library" default="help">
|
||||||
|
|
||||||
|
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||||
|
It contains the path to the SDK. It should *NOT* be checked into
|
||||||
|
Version Control Systems. -->
|
||||||
|
<property file="local.properties" />
|
||||||
|
|
||||||
|
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||||
|
'android' tool to add properties to it.
|
||||||
|
This is the place to change some Ant specific build properties.
|
||||||
|
Here are some properties you may want to change/update:
|
||||||
|
|
||||||
|
source.dir
|
||||||
|
The name of the source directory. Default is 'src'.
|
||||||
|
out.dir
|
||||||
|
The name of the output directory. Default is 'bin'.
|
||||||
|
|
||||||
|
For other overridable properties, look at the beginning of the rules
|
||||||
|
files in the SDK, at tools/ant/build.xml
|
||||||
|
|
||||||
|
Properties related to the SDK location or the project target should
|
||||||
|
be updated using the 'android' tool with the 'update' action.
|
||||||
|
|
||||||
|
This file is an integral part of the build system for your
|
||||||
|
application and should be checked into Version Control Systems.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<property file="ant.properties" />
|
||||||
|
|
||||||
|
<!-- The project.properties file is created and updated by the 'android'
|
||||||
|
tool, as well as ADT.
|
||||||
|
|
||||||
|
This contains project specific properties such as project target, and library
|
||||||
|
dependencies. Lower level build properties are stored in ant.properties
|
||||||
|
(or in .classpath for Eclipse projects).
|
||||||
|
|
||||||
|
This file is an integral part of the build system for your
|
||||||
|
application and should be checked into Version Control Systems. -->
|
||||||
|
<loadproperties srcFile="project.properties" />
|
||||||
|
|
||||||
|
<!-- quick check on sdk.dir -->
|
||||||
|
<fail
|
||||||
|
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through an env var"
|
||||||
|
unless="sdk.dir"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- extension targets. Uncomment the ones where you want to do custom work
|
||||||
|
in between standard targets -->
|
||||||
|
<!--
|
||||||
|
<target name="-pre-build">
|
||||||
|
</target>
|
||||||
|
<target name="-pre-compile">
|
||||||
|
</target>
|
||||||
|
|
||||||
|
/* This is typically used for code obfuscation.
|
||||||
|
Compiled code location: ${out.classes.absolute.dir}
|
||||||
|
If this is not done in place, override ${out.dex.input.absolute.dir} */
|
||||||
|
<target name="-post-compile">
|
||||||
|
</target>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Import the actual build file.
|
||||||
|
|
||||||
|
To customize existing targets, there are two options:
|
||||||
|
- Customize only one target:
|
||||||
|
- copy/paste the target into this file, *before* the
|
||||||
|
<import> task.
|
||||||
|
- customize it to your needs.
|
||||||
|
- Customize the whole content of build.xml
|
||||||
|
- copy/paste the content of the rules files (minus the top node)
|
||||||
|
into this file, replacing the <import> task.
|
||||||
|
- customize to your needs.
|
||||||
|
|
||||||
|
***********************
|
||||||
|
****** IMPORTANT ******
|
||||||
|
***********************
|
||||||
|
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||||
|
in order to avoid having your file be overridden by tools such as "android update project"
|
||||||
|
-->
|
||||||
|
<!-- version-tag: 1 -->
|
||||||
|
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||||
|
|
||||||
|
</project>
|
||||||
@ -0,0 +1,115 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE module PUBLIC
|
||||||
|
"-//Puppy Crawl//DTD Check Configuration 1.2//EN"
|
||||||
|
"http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
|
||||||
|
|
||||||
|
<module name="Checker">
|
||||||
|
<!--module name="NewlineAtEndOfFile"/-->
|
||||||
|
<module name="FileLength"/>
|
||||||
|
<module name="FileTabCharacter"/>
|
||||||
|
|
||||||
|
<!-- Trailing spaces -->
|
||||||
|
<module name="RegexpSingleline">
|
||||||
|
<property name="format" value="\s+$"/>
|
||||||
|
<property name="message" value="Line has trailing spaces."/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="TreeWalker">
|
||||||
|
<property name="cacheFile" value="${checkstyle.cache.file}"/>
|
||||||
|
|
||||||
|
<!-- Checks for Javadoc comments. -->
|
||||||
|
<!-- See http://checkstyle.sf.net/config_javadoc.html -->
|
||||||
|
<!--module name="JavadocMethod"/-->
|
||||||
|
<!--module name="JavadocType"/-->
|
||||||
|
<!--module name="JavadocVariable"/-->
|
||||||
|
<!--module name="JavadocStyle"/-->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Checks for Naming Conventions. -->
|
||||||
|
<!-- See http://checkstyle.sf.net/config_naming.html -->
|
||||||
|
<module name="ConstantName"/>
|
||||||
|
<module name="LocalFinalVariableName"/>
|
||||||
|
<module name="LocalVariableName"/>
|
||||||
|
<module name="MemberName"/>
|
||||||
|
<module name="MethodName"/>
|
||||||
|
<module name="PackageName"/>
|
||||||
|
<module name="ParameterName"/>
|
||||||
|
<module name="StaticVariableName"/>
|
||||||
|
<module name="TypeName"/>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Checks for imports -->
|
||||||
|
<!-- See http://checkstyle.sf.net/config_import.html -->
|
||||||
|
<module name="AvoidStarImport"/>
|
||||||
|
<module name="IllegalImport"/> <!-- defaults to sun.* packages -->
|
||||||
|
<module name="RedundantImport"/>
|
||||||
|
<module name="UnusedImports"/>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Checks for Size Violations. -->
|
||||||
|
<!-- See http://checkstyle.sf.net/config_sizes.html -->
|
||||||
|
<!--module name="LineLength"/-->
|
||||||
|
<!--module name="MethodLength"/-->
|
||||||
|
<!--module name="ParameterNumber"/-->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Checks for whitespace -->
|
||||||
|
<!-- See http://checkstyle.sf.net/config_whitespace.html -->
|
||||||
|
<!--module name="EmptyForIteratorPad"/-->
|
||||||
|
<!--module name="MethodParamPad"/-->
|
||||||
|
<!--module name="NoWhitespaceAfter"/-->
|
||||||
|
<!--module name="NoWhitespaceBefore"/-->
|
||||||
|
<!--module name="OperatorWrap"/-->
|
||||||
|
<!--module name="ParenPad"/-->
|
||||||
|
<!--module name="TypecastParenPad"/-->
|
||||||
|
<!--module name="WhitespaceAfter"/-->
|
||||||
|
<!--module name="WhitespaceAround"/-->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Modifier Checks -->
|
||||||
|
<!-- See http://checkstyle.sf.net/config_modifiers.html -->
|
||||||
|
<!--module name="ModifierOrder"/-->
|
||||||
|
<!--module name="RedundantModifier"/-->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Checks for blocks. You know, those {}'s -->
|
||||||
|
<!-- See http://checkstyle.sf.net/config_blocks.html -->
|
||||||
|
<!--module name="AvoidNestedBlocks"/-->
|
||||||
|
<!--module name="EmptyBlock"/-->
|
||||||
|
<!--module name="LeftCurly"/-->
|
||||||
|
<!--module name="NeedBraces"/-->
|
||||||
|
<!--module name="RightCurly"/-->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Checks for common coding problems -->
|
||||||
|
<!-- See http://checkstyle.sf.net/config_coding.html -->
|
||||||
|
<!--module name="AvoidInlineConditionals"/-->
|
||||||
|
<!--module name="DoubleCheckedLocking"/--> <!-- MY FAVOURITE -->
|
||||||
|
<!--module name="EmptyStatement"/-->
|
||||||
|
<!--module name="EqualsHashCode"/-->
|
||||||
|
<!--module name="HiddenField"/-->
|
||||||
|
<!--module name="IllegalInstantiation"/-->
|
||||||
|
<!--module name="InnerAssignment"/-->
|
||||||
|
<!--module name="MagicNumber"/-->
|
||||||
|
<!--module name="MissingSwitchDefault"/-->
|
||||||
|
<!--module name="RedundantThrows"/-->
|
||||||
|
<!--module name="SimplifyBooleanExpression"/-->
|
||||||
|
<!--module name="SimplifyBooleanReturn"/-->
|
||||||
|
|
||||||
|
<!-- Checks for class design -->
|
||||||
|
<!-- See http://checkstyle.sf.net/config_design.html -->
|
||||||
|
<!--module name="DesignForExtension"/-->
|
||||||
|
<!--module name="FinalClass"/-->
|
||||||
|
<!--module name="HideUtilityClassConstructor"/-->
|
||||||
|
<!--module name="InterfaceIsType"/-->
|
||||||
|
<!--module name="VisibilityModifier"/-->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Miscellaneous other checks. -->
|
||||||
|
<!-- See http://checkstyle.sf.net/config_misc.html -->
|
||||||
|
<!--module name="ArrayTypeStyle"/-->
|
||||||
|
<!--module name="FinalParameters"/-->
|
||||||
|
<!--module name="TodoComment"/-->
|
||||||
|
<!--module name="UpperEll"/-->
|
||||||
|
</module>
|
||||||
|
</module>
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.viewpagerindicator</groupId>
|
||||||
|
<artifactId>library</artifactId>
|
||||||
|
<name>Android-ViewPagerIndicator</name>
|
||||||
|
<packaging>apklib</packaging>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.viewpagerindicator</groupId>
|
||||||
|
<artifactId>parent</artifactId>
|
||||||
|
<version>2.2.2</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>android</groupId>
|
||||||
|
<artifactId>android</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>android.support</groupId>
|
||||||
|
<artifactId>compatibility-v4</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<sourceDirectory>src</sourceDirectory>
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
|
||||||
|
<artifactId>maven-android-plugin</artifactId>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<skip>true</skip>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<configLocation>${project.basedir}/checkstyle.xml</configLocation>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>verify</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>checkstyle</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
-optimizationpasses 5
|
||||||
|
-dontusemixedcaseclassnames
|
||||||
|
-dontskipnonpubliclibraryclasses
|
||||||
|
-dontpreverify
|
||||||
|
-verbose
|
||||||
|
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
|
||||||
|
|
||||||
|
-keep public class * extends android.app.Activity
|
||||||
|
-keep public class * extends android.app.Application
|
||||||
|
-keep public class * extends android.app.Service
|
||||||
|
-keep public class * extends android.content.BroadcastReceiver
|
||||||
|
-keep public class * extends android.content.ContentProvider
|
||||||
|
-keep public class * extends android.app.backup.BackupAgentHelper
|
||||||
|
-keep public class * extends android.preference.Preference
|
||||||
|
-keep public class com.android.vending.licensing.ILicensingService
|
||||||
|
|
||||||
|
-keepclasseswithmembernames class * {
|
||||||
|
native <methods>;
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclasseswithmembers class * {
|
||||||
|
public <init>(android.content.Context, android.util.AttributeSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclasseswithmembers class * {
|
||||||
|
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclassmembers class * extends android.app.Activity {
|
||||||
|
public void *(android.view.View);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclassmembers enum * {
|
||||||
|
public static **[] values();
|
||||||
|
public static ** valueOf(java.lang.String);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keep class * implements android.os.Parcelable {
|
||||||
|
public static final android.os.Parcelable$Creator *;
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
# This file is automatically generated by Android Tools.
|
||||||
|
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||||
|
#
|
||||||
|
# This file must be checked in Version Control Systems.
|
||||||
|
#
|
||||||
|
# To customize properties used by the Ant build system use,
|
||||||
|
# "ant.properties", and override values to adapt the script to your
|
||||||
|
# project structure.
|
||||||
|
|
||||||
|
android.library=true
|
||||||
|
# Project target.
|
||||||
|
target=android-4
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2010 The Android Open Source Project
|
||||||
|
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:state_enabled="false" android:color="@color/vpi__bright_foreground_disabled_holo_dark"/>
|
||||||
|
<item android:state_window_focused="false" android:color="@color/vpi__bright_foreground_holo_dark"/>
|
||||||
|
<item android:state_pressed="true" android:color="@color/vpi__bright_foreground_holo_dark"/>
|
||||||
|
<item android:state_selected="true" android:color="@color/vpi__bright_foreground_holo_dark"/>
|
||||||
|
<!--item android:state_activated="true" android:color="@color/vpi__bright_foreground_holo_dark"/-->
|
||||||
|
<item android:color="@color/vpi__bright_foreground_holo_dark"/> <!-- not selected -->
|
||||||
|
</selector>
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2010 The Android Open Source Project
|
||||||
|
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:state_enabled="false" android:color="@color/vpi__bright_foreground_disabled_holo_light"/>
|
||||||
|
<item android:state_window_focused="false" android:color="@color/vpi__bright_foreground_holo_light"/>
|
||||||
|
<item android:state_pressed="true" android:color="@color/vpi__bright_foreground_holo_light"/>
|
||||||
|
<item android:state_selected="true" android:color="@color/vpi__bright_foreground_holo_light"/>
|
||||||
|
<!--item android:state_activated="true" android:color="@color/vpi__bright_foreground_holo_light"/-->
|
||||||
|
<item android:color="@color/vpi__bright_foreground_holo_light"/> <!-- not selected -->
|
||||||
|
|
||||||
|
</selector>
|
||||||
|
|
||||||
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 148 B |
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 146 B |
|
After Width: | Height: | Size: 153 B |
|
After Width: | Height: | Size: 145 B |
|
After Width: | Height: | Size: 148 B |
|
After Width: | Height: | Size: 151 B |
|
After Width: | Height: | Size: 150 B |
|
After Width: | Height: | Size: 150 B |
|
After Width: | Height: | Size: 157 B |
|
After Width: | Height: | Size: 155 B |
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 153 B |
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 148 B |
|
After Width: | Height: | Size: 166 B |
|
After Width: | Height: | Size: 149 B |
@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2008 The Android Open Source Project
|
||||||
|
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<!-- Non focused states -->
|
||||||
|
<item android:state_focused="false" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/vpi__tab_unselected_holo" />
|
||||||
|
<item android:state_focused="false" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/vpi__tab_selected_holo" />
|
||||||
|
|
||||||
|
<!-- Focused states -->
|
||||||
|
<item android:state_focused="true" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/vpi__tab_unselected_focused_holo" />
|
||||||
|
<item android:state_focused="true" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/vpi__tab_selected_focused_holo" />
|
||||||
|
|
||||||
|
<!-- Pressed -->
|
||||||
|
<!-- Non focused states -->
|
||||||
|
<item android:state_focused="false" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/vpi__tab_unselected_pressed_holo" />
|
||||||
|
<item android:state_focused="false" android:state_selected="true" android:state_pressed="true" android:drawable="@drawable/vpi__tab_selected_pressed_holo" />
|
||||||
|
|
||||||
|
<!-- Focused states -->
|
||||||
|
<item android:state_focused="true" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/vpi__tab_unselected_pressed_holo" />
|
||||||
|
<item android:state_focused="true" android:state_selected="true" android:state_pressed="true" android:drawable="@drawable/vpi__tab_selected_pressed_holo" />
|
||||||
|
</selector>
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<view
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
class="com.viewpagerindicator.TabPageIndicator$TabView"
|
||||||
|
style="?attr/vpiTabPageIndicatorStyle">
|
||||||
|
<TextView
|
||||||
|
android:id="@android:id/text1"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
style="?attr/vpiTabTextStyle" />
|
||||||
|
</view>
|
||||||
@ -0,0 +1,84 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2011 Patrik Åkerfeldt
|
||||||
|
Copyright (C) 2011 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources>
|
||||||
|
<declare-styleable name="ViewPagerIndicator">
|
||||||
|
<!-- Style of the circle indicator. -->
|
||||||
|
<attr name="vpiCirclePageIndicatorStyle" format="reference"/>
|
||||||
|
|
||||||
|
<!-- Style of the title indicator. -->
|
||||||
|
<attr name="vpiTitlePageIndicatorStyle" format="reference"/>
|
||||||
|
|
||||||
|
<!-- Style of the tab indicator. -->
|
||||||
|
<attr name="vpiTabPageIndicatorStyle" format="reference"/>
|
||||||
|
<!-- Style of the text in a tab. -->
|
||||||
|
<attr name="vpiTabTextStyle" format="reference"/>
|
||||||
|
</declare-styleable>
|
||||||
|
|
||||||
|
<declare-styleable name="CirclePageIndicator">
|
||||||
|
<!-- Whether or not the indicators should be centered. -->
|
||||||
|
<attr name="centered" format="boolean" />
|
||||||
|
<!-- Color of the filled circle that represents the current page. -->
|
||||||
|
<attr name="fillColor" format="color" />
|
||||||
|
<!-- Orientation of the indicator. -->
|
||||||
|
<attr name="orientation">
|
||||||
|
<enum name="horizontal" value="0" />
|
||||||
|
<enum name="vertical" value="1" />
|
||||||
|
</attr>
|
||||||
|
<!-- Radius of the circles. This is also the spacing between circles. -->
|
||||||
|
<attr name="radius" format="dimension" />
|
||||||
|
<!-- Whether or not the selected indicator snaps to the circles. -->
|
||||||
|
<attr name="snap" format="boolean" />
|
||||||
|
<!-- Color of the open circles. -->
|
||||||
|
<attr name="strokeColor" format="color" />
|
||||||
|
<!-- Width of the stroke used to draw the circles. -->
|
||||||
|
<attr name="strokeWidth" format="dimension" />
|
||||||
|
</declare-styleable>
|
||||||
|
|
||||||
|
<declare-styleable name="TitlePageIndicator">
|
||||||
|
<!-- Screen edge padding. -->
|
||||||
|
<attr name="clipPadding" format="dimension" />
|
||||||
|
<!-- Color of the footer line and indicator. -->
|
||||||
|
<attr name="footerColor" format="color" />
|
||||||
|
<!-- Height of the footer line. -->
|
||||||
|
<attr name="footerLineHeight" format="dimension" />
|
||||||
|
<!-- Style of the indicator. Default is triangle. -->
|
||||||
|
<attr name="footerIndicatorStyle">
|
||||||
|
<enum name="none" value="0" />
|
||||||
|
<enum name="triangle" value="1" />
|
||||||
|
<enum name="underline" value="2" />
|
||||||
|
</attr>
|
||||||
|
<!-- Height of the indicator above the footer line. -->
|
||||||
|
<attr name="footerIndicatorHeight" format="dimension" />
|
||||||
|
<!-- Left and right padding of the underline indicator. -->
|
||||||
|
<attr name="footerIndicatorUnderlinePadding" format="dimension" />
|
||||||
|
<!-- Padding between the bottom of the title and the footer. -->
|
||||||
|
<attr name="footerPadding" format="dimension" />
|
||||||
|
<!-- Color of the selected title. -->
|
||||||
|
<attr name="selectedColor" format="color" />
|
||||||
|
<!-- Whether or not the selected item is displayed as bold. -->
|
||||||
|
<attr name="selectedBold" format="boolean" />
|
||||||
|
<!-- Color of regular titles. -->
|
||||||
|
<attr name="textColor" format="color" />
|
||||||
|
<!-- Size of title text. -->
|
||||||
|
<attr name="textSize" format="dimension" />
|
||||||
|
<!-- Padding between titles when bumping into each other. -->
|
||||||
|
<attr name="titlePadding" format="dimension" />
|
||||||
|
<!-- Padding between titles and the top of the View. -->
|
||||||
|
<attr name="topPadding" format="dimension" />
|
||||||
|
</declare-styleable>
|
||||||
|
</resources>
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2011 The Android Open Source Project
|
||||||
|
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources>
|
||||||
|
<color name="vpi__background_holo_dark">#ff000000</color>
|
||||||
|
<color name="vpi__background_holo_light">#fff3f3f3</color>
|
||||||
|
<color name="vpi__bright_foreground_holo_dark">@color/vpi__background_holo_light</color>
|
||||||
|
<color name="vpi__bright_foreground_holo_light">@color/vpi__background_holo_dark</color>
|
||||||
|
<color name="vpi__bright_foreground_disabled_holo_dark">#ff4c4c4c</color>
|
||||||
|
<color name="vpi__bright_foreground_disabled_holo_light">#ffb2b2b2</color>
|
||||||
|
<color name="vpi__bright_foreground_inverse_holo_dark">@color/vpi__bright_foreground_holo_light</color>
|
||||||
|
<color name="vpi__bright_foreground_inverse_holo_light">@color/vpi__bright_foreground_holo_dark</color>
|
||||||
|
</resources>
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2011 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources>
|
||||||
|
<bool name="default_circle_indicator_centered">true</bool>
|
||||||
|
<color name="default_circle_indicator_fill_color">#FFFFFFFF</color>
|
||||||
|
<integer name="default_circle_indicator_orientation">0</integer>
|
||||||
|
<dimen name="default_circle_indicator_radius">3dp</dimen>
|
||||||
|
<bool name="default_circle_indicator_snap">false</bool>
|
||||||
|
<color name="default_circle_indicator_stroke_color">#FFDDDDDD</color>
|
||||||
|
<dimen name="default_circle_indicator_stroke_width">1dp</dimen>
|
||||||
|
|
||||||
|
<dimen name="default_title_indicator_clip_padding">4dp</dimen>
|
||||||
|
<color name="default_title_indicator_footer_color">#FF6899FF</color>
|
||||||
|
<dimen name="default_title_indicator_footer_line_height">2dp</dimen>
|
||||||
|
<integer name="default_title_indicator_footer_indicator_style">2</integer>
|
||||||
|
<dimen name="default_title_indicator_footer_indicator_height">4dp</dimen>
|
||||||
|
<dimen name="default_title_indicator_footer_indicator_underline_padding">20dp</dimen>
|
||||||
|
<dimen name="default_title_indicator_footer_padding">7dp</dimen>
|
||||||
|
<color name="default_title_indicator_selected_color">#FFFFFFFF</color>
|
||||||
|
<bool name="default_title_indicator_selected_bold">true</bool>
|
||||||
|
<color name="default_title_indicator_text_color">#BBFFFFFF</color>
|
||||||
|
<dimen name="default_title_indicator_text_size">15sp</dimen>
|
||||||
|
<dimen name="default_title_indicator_title_padding">5dp</dimen>
|
||||||
|
<dimen name="default_title_indicator_top_padding">7dp</dimen>
|
||||||
|
</resources>
|
||||||
@ -0,0 +1,72 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2011 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources>
|
||||||
|
<style name="Theme.PageIndicatorDefaults" parent="android:Theme">
|
||||||
|
<item name="vpiCirclePageIndicatorStyle">@style/Widget.CirclePageIndicator</item>
|
||||||
|
<item name="vpiTitlePageIndicatorStyle">@style/Widget.TitlePageIndicator</item>
|
||||||
|
<item name="vpiTabPageIndicatorStyle">@style/Widget.TabPageIndicator</item>
|
||||||
|
<item name="vpiTabTextStyle">@style/Widget.TabPageIndicator.Text</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="Widget"></style>
|
||||||
|
|
||||||
|
<style name="Widget.CirclePageIndicator" parent="Widget">
|
||||||
|
<item name="centered">@bool/default_circle_indicator_centered</item>
|
||||||
|
<item name="fillColor">@color/default_circle_indicator_fill_color</item>
|
||||||
|
<item name="orientation">@integer/default_circle_indicator_orientation</item>
|
||||||
|
<item name="radius">@dimen/default_circle_indicator_radius</item>
|
||||||
|
<item name="snap">@bool/default_circle_indicator_snap</item>
|
||||||
|
<item name="strokeColor">@color/default_circle_indicator_stroke_color</item>
|
||||||
|
<item name="strokeWidth">@dimen/default_circle_indicator_stroke_width</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="Widget.TitlePageIndicator" parent="Widget">
|
||||||
|
<item name="clipPadding">@dimen/default_title_indicator_clip_padding</item>
|
||||||
|
<item name="footerColor">@color/default_title_indicator_footer_color</item>
|
||||||
|
<item name="footerLineHeight">@dimen/default_title_indicator_footer_line_height</item>
|
||||||
|
<item name="footerIndicatorStyle">@integer/default_title_indicator_footer_indicator_style</item>
|
||||||
|
<item name="footerIndicatorHeight">@dimen/default_title_indicator_footer_indicator_height</item>
|
||||||
|
<item name="footerIndicatorUnderlinePadding">@dimen/default_title_indicator_footer_indicator_underline_padding</item>
|
||||||
|
<item name="footerPadding">@dimen/default_title_indicator_footer_padding</item>
|
||||||
|
<item name="selectedColor">@color/default_title_indicator_selected_color</item>
|
||||||
|
<item name="selectedBold">@bool/default_title_indicator_selected_bold</item>
|
||||||
|
<item name="textColor">@color/default_title_indicator_text_color</item>
|
||||||
|
<item name="textSize">@dimen/default_title_indicator_text_size</item>
|
||||||
|
<item name="titlePadding">@dimen/default_title_indicator_title_padding</item>
|
||||||
|
<item name="topPadding">@dimen/default_title_indicator_top_padding</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="Widget.TabPageIndicator" parent="Widget">
|
||||||
|
<item name="android:gravity">center_horizontal</item>
|
||||||
|
<item name="android:background">@drawable/vpi__tab_indicator</item>
|
||||||
|
<item name="android:paddingLeft">22dip</item>
|
||||||
|
<item name="android:paddingRight">22dip</item>
|
||||||
|
<item name="android:paddingTop">12dp</item>
|
||||||
|
<item name="android:paddingBottom">12dp</item>
|
||||||
|
</style>
|
||||||
|
<style name="Widget.TabPageIndicator.Text" parent="Widget">
|
||||||
|
<item name="android:textAppearance">@style/TextAppearance.TabPageIndicator</item>
|
||||||
|
<item name="android:textColor">@color/vpi__dark_theme</item>
|
||||||
|
<item name="android:textSize">12sp</item>
|
||||||
|
<item name="android:textStyle">bold</item>
|
||||||
|
<item name="android:maxLines">1</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="TextAppearance.TabPageIndicator" parent="Widget">
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</resources>
|
||||||
@ -0,0 +1,526 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011 Patrik Akerfeldt
|
||||||
|
* Copyright (C) 2011 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.
|
||||||
|
*/
|
||||||
|
package com.viewpagerindicator;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Paint.Style;
|
||||||
|
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 circles (one for each view). The current view position is filled and
|
||||||
|
* others are only stroked.
|
||||||
|
*/
|
||||||
|
public class CirclePageIndicator extends View implements PageIndicator {
|
||||||
|
public static final int HORIZONTAL = 0;
|
||||||
|
public static final int VERTICAL = 1;
|
||||||
|
|
||||||
|
private float mRadius;
|
||||||
|
private final Paint mPaintStroke;
|
||||||
|
private final Paint mPaintFill;
|
||||||
|
private ViewPager mViewPager;
|
||||||
|
private ViewPager.OnPageChangeListener mListener;
|
||||||
|
private int mCurrentPage;
|
||||||
|
private int mSnapPage;
|
||||||
|
private int mCurrentOffset;
|
||||||
|
private int mScrollState;
|
||||||
|
private int mPageSize;
|
||||||
|
private int mOrientation;
|
||||||
|
private boolean mCentered;
|
||||||
|
private boolean mSnap;
|
||||||
|
|
||||||
|
private static final int INVALID_POINTER = -1;
|
||||||
|
|
||||||
|
private int mTouchSlop;
|
||||||
|
private float mLastMotionX = -1;
|
||||||
|
private int mActivePointerId = INVALID_POINTER;
|
||||||
|
private boolean mIsDragging;
|
||||||
|
|
||||||
|
|
||||||
|
public CirclePageIndicator(Context context) {
|
||||||
|
this(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CirclePageIndicator(Context context, AttributeSet attrs) {
|
||||||
|
this(context, attrs, R.attr.vpiCirclePageIndicatorStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CirclePageIndicator(Context context, AttributeSet attrs, int defStyle) {
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
|
||||||
|
//Load defaults from resources
|
||||||
|
final Resources res = getResources();
|
||||||
|
final int defaultFillColor = res.getColor(R.color.default_circle_indicator_fill_color);
|
||||||
|
final int defaultOrientation = res.getInteger(R.integer.default_circle_indicator_orientation);
|
||||||
|
final int defaultStrokeColor = res.getColor(R.color.default_circle_indicator_stroke_color);
|
||||||
|
final float defaultStrokeWidth = res.getDimension(R.dimen.default_circle_indicator_stroke_width);
|
||||||
|
final float defaultRadius = res.getDimension(R.dimen.default_circle_indicator_radius);
|
||||||
|
final boolean defaultCentered = res.getBoolean(R.bool.default_circle_indicator_centered);
|
||||||
|
final boolean defaultSnap = res.getBoolean(R.bool.default_circle_indicator_snap);
|
||||||
|
|
||||||
|
//Retrieve styles attributes
|
||||||
|
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CirclePageIndicator, defStyle, R.style.Widget_CirclePageIndicator);
|
||||||
|
|
||||||
|
mCentered = a.getBoolean(R.styleable.CirclePageIndicator_centered, defaultCentered);
|
||||||
|
mOrientation = a.getInt(R.styleable.CirclePageIndicator_orientation, defaultOrientation);
|
||||||
|
mPaintStroke = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
mPaintStroke.setStyle(Style.STROKE);
|
||||||
|
mPaintStroke.setColor(a.getColor(R.styleable.CirclePageIndicator_strokeColor, defaultStrokeColor));
|
||||||
|
mPaintStroke.setStrokeWidth(a.getDimension(R.styleable.CirclePageIndicator_strokeWidth, defaultStrokeWidth));
|
||||||
|
mPaintFill = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
mPaintFill.setStyle(Style.FILL);
|
||||||
|
mPaintFill.setColor(a.getColor(R.styleable.CirclePageIndicator_fillColor, defaultFillColor));
|
||||||
|
mRadius = a.getDimension(R.styleable.CirclePageIndicator_radius, defaultRadius);
|
||||||
|
mSnap = a.getBoolean(R.styleable.CirclePageIndicator_snap, defaultSnap);
|
||||||
|
|
||||||
|
a.recycle();
|
||||||
|
|
||||||
|
final ViewConfiguration configuration = ViewConfiguration.get(context);
|
||||||
|
mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setCentered(boolean centered) {
|
||||||
|
mCentered = centered;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCentered() {
|
||||||
|
return mCentered;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFillColor(int fillColor) {
|
||||||
|
mPaintFill.setColor(fillColor);
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFillColor() {
|
||||||
|
return mPaintFill.getColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrientation(int orientation) {
|
||||||
|
switch (orientation) {
|
||||||
|
case HORIZONTAL:
|
||||||
|
case VERTICAL:
|
||||||
|
mOrientation = orientation;
|
||||||
|
updatePageSize();
|
||||||
|
requestLayout();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Orientation must be either HORIZONTAL or VERTICAL.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getOrientation() {
|
||||||
|
return mOrientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeColor(int strokeColor) {
|
||||||
|
mPaintStroke.setColor(strokeColor);
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStrokeColor() {
|
||||||
|
return mPaintStroke.getColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeWidth(float strokeWidth) {
|
||||||
|
mPaintStroke.setStrokeWidth(strokeWidth);
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getStrokeWidth() {
|
||||||
|
return mPaintStroke.getStrokeWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRadius(float radius) {
|
||||||
|
mRadius = radius;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getRadius() {
|
||||||
|
return mRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSnap(boolean snap) {
|
||||||
|
mSnap = snap;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSnap() {
|
||||||
|
return mSnap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see android.view.View#onDraw(android.graphics.Canvas)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void onDraw(Canvas canvas) {
|
||||||
|
super.onDraw(canvas);
|
||||||
|
|
||||||
|
if (mViewPager == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final int count = mViewPager.getAdapter().getCount();
|
||||||
|
if (count == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int longSize;
|
||||||
|
int longPaddingBefore;
|
||||||
|
int longPaddingAfter;
|
||||||
|
int shortPaddingBefore;
|
||||||
|
if (mOrientation == HORIZONTAL) {
|
||||||
|
longSize = getWidth();
|
||||||
|
longPaddingBefore = getPaddingLeft();
|
||||||
|
longPaddingAfter = getPaddingRight();
|
||||||
|
shortPaddingBefore = getPaddingTop();
|
||||||
|
} else {
|
||||||
|
longSize = getHeight();
|
||||||
|
longPaddingBefore = getPaddingTop();
|
||||||
|
longPaddingAfter = getPaddingBottom();
|
||||||
|
shortPaddingBefore = getPaddingLeft();
|
||||||
|
}
|
||||||
|
|
||||||
|
final float threeRadius = mRadius * 3;
|
||||||
|
final float shortOffset = shortPaddingBefore + mRadius;
|
||||||
|
float longOffset = longPaddingBefore + mRadius;
|
||||||
|
if (mCentered) {
|
||||||
|
longOffset += ((longSize - longPaddingBefore - longPaddingAfter) / 2.0f) - ((count * threeRadius) / 2.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
float dX;
|
||||||
|
float dY;
|
||||||
|
|
||||||
|
//Draw the filled circle according to the current scroll
|
||||||
|
float cx = (mSnap ? mSnapPage : mCurrentPage) * threeRadius;
|
||||||
|
if (!mSnap && (mPageSize != 0)) {
|
||||||
|
cx += (mCurrentOffset * 1.0f / mPageSize) * threeRadius;
|
||||||
|
}
|
||||||
|
if (mOrientation == HORIZONTAL) {
|
||||||
|
dX = longOffset + cx;
|
||||||
|
dY = shortOffset;
|
||||||
|
} else {
|
||||||
|
dX = shortOffset;
|
||||||
|
dY = longOffset + cx;
|
||||||
|
}
|
||||||
|
canvas.drawCircle(dX, dY, mRadius - getResources().getDimension(R.dimen.default_circle_indicator_stroke_width)/2
|
||||||
|
, mPaintFill);
|
||||||
|
|
||||||
|
//Draw stroked circles
|
||||||
|
for (int iLoop = 0; iLoop < count; iLoop++) {
|
||||||
|
float drawLong = longOffset + (iLoop * threeRadius);
|
||||||
|
if (mOrientation == HORIZONTAL) {
|
||||||
|
dX = drawLong;
|
||||||
|
dY = shortOffset;
|
||||||
|
} else {
|
||||||
|
dX = shortOffset;
|
||||||
|
dY = drawLong;
|
||||||
|
}
|
||||||
|
canvas.drawCircle(dX, dY, mRadius, mPaintStroke);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onTouchEvent(android.view.MotionEvent ev) {
|
||||||
|
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) {
|
||||||
|
if (!mViewPager.isFakeDragging()) {
|
||||||
|
mViewPager.beginFakeDrag();
|
||||||
|
}
|
||||||
|
|
||||||
|
mLastMotionX = x;
|
||||||
|
|
||||||
|
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 view) {
|
||||||
|
if (view.getAdapter() == null) {
|
||||||
|
throw new IllegalStateException("ViewPager does not have adapter instance.");
|
||||||
|
}
|
||||||
|
mViewPager = view;
|
||||||
|
mViewPager.setOnPageChangeListener(this);
|
||||||
|
updatePageSize();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePageSize() {
|
||||||
|
if (mViewPager != null) {
|
||||||
|
mPageSize = (mOrientation == HORIZONTAL) ? mViewPager.getWidth() : mViewPager.getHeight();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
mCurrentOffset = positionOffsetPixels;
|
||||||
|
updatePageSize();
|
||||||
|
invalidate();
|
||||||
|
|
||||||
|
if (mListener != null) {
|
||||||
|
mListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPageSelected(int position) {
|
||||||
|
if (mSnap || mScrollState == ViewPager.SCROLL_STATE_IDLE) {
|
||||||
|
mCurrentPage = position;
|
||||||
|
mSnapPage = position;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mListener != null) {
|
||||||
|
mListener.onPageSelected(position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
|
||||||
|
mListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see android.view.View#onMeasure(int, int)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
|
if (mOrientation == HORIZONTAL) {
|
||||||
|
setMeasuredDimension(measureLong(widthMeasureSpec), measureShort(heightMeasureSpec));
|
||||||
|
} else {
|
||||||
|
setMeasuredDimension(measureShort(widthMeasureSpec), measureLong(heightMeasureSpec));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the width of this view
|
||||||
|
*
|
||||||
|
* @param measureSpec
|
||||||
|
* A measureSpec packed into an int
|
||||||
|
* @return The width of the view, honoring constraints from measureSpec
|
||||||
|
*/
|
||||||
|
private int measureLong(int measureSpec) {
|
||||||
|
int result = 0;
|
||||||
|
int specMode = MeasureSpec.getMode(measureSpec);
|
||||||
|
int specSize = MeasureSpec.getSize(measureSpec);
|
||||||
|
|
||||||
|
if ((specMode == MeasureSpec.EXACTLY) || (mViewPager == null)) {
|
||||||
|
//We were told how big to be
|
||||||
|
result = specSize;
|
||||||
|
} else {
|
||||||
|
//Calculate the width according the views count
|
||||||
|
final int count = mViewPager.getAdapter().getCount();
|
||||||
|
result = (int)(getPaddingLeft() + getPaddingRight()
|
||||||
|
+ (count * 2 * mRadius) + (count - 1) * mRadius + 1);
|
||||||
|
//Respect AT_MOST value if that was what is called for by measureSpec
|
||||||
|
if (specMode == MeasureSpec.AT_MOST) {
|
||||||
|
result = Math.min(result, specSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the height of this view
|
||||||
|
*
|
||||||
|
* @param measureSpec
|
||||||
|
* A measureSpec packed into an int
|
||||||
|
* @return The height of the view, honoring constraints from measureSpec
|
||||||
|
*/
|
||||||
|
private int measureShort(int measureSpec) {
|
||||||
|
int result = 0;
|
||||||
|
int specMode = MeasureSpec.getMode(measureSpec);
|
||||||
|
int specSize = MeasureSpec.getSize(measureSpec);
|
||||||
|
|
||||||
|
if (specMode == MeasureSpec.EXACTLY) {
|
||||||
|
//We were told how big to be
|
||||||
|
result = specSize;
|
||||||
|
} else {
|
||||||
|
//Measure the height
|
||||||
|
result = (int)(2 * mRadius + getPaddingTop() + getPaddingBottom() + 1);
|
||||||
|
//Respect AT_MOST value if that was what is called for by measureSpec
|
||||||
|
if (specMode == MeasureSpec.AT_MOST) {
|
||||||
|
result = Math.min(result, specSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRestoreInstanceState(Parcelable state) {
|
||||||
|
SavedState savedState = (SavedState)state;
|
||||||
|
super.onRestoreInstanceState(savedState.getSuperState());
|
||||||
|
mCurrentPage = savedState.currentPage;
|
||||||
|
mSnapPage = 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 Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
|
||||||
|
@Override
|
||||||
|
public SavedState createFromParcel(Parcel in) {
|
||||||
|
return new SavedState(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SavedState[] newArray(int size) {
|
||||||
|
return new SavedState[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011 Patrik Akerfeldt
|
||||||
|
* Copyright (C) 2011 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.viewpagerindicator;
|
||||||
|
|
||||||
|
import android.support.v4.view.ViewPager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A PageIndicator is responsible to show an visual indicator on the total views
|
||||||
|
* number and the current visible view.
|
||||||
|
*/
|
||||||
|
public interface PageIndicator extends ViewPager.OnPageChangeListener {
|
||||||
|
/**
|
||||||
|
* Bind the indicator to a ViewPager.
|
||||||
|
*
|
||||||
|
* @param view
|
||||||
|
*/
|
||||||
|
public void setViewPager(ViewPager view);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bind the indicator to a ViewPager.
|
||||||
|
*
|
||||||
|
* @param view
|
||||||
|
* @param initialPosition
|
||||||
|
*/
|
||||||
|
public void setViewPager(ViewPager view, int initialPosition);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Set the current page of both the ViewPager and indicator.</p>
|
||||||
|
*
|
||||||
|
* <p>This <strong>must</strong> be used if you need to set the page before
|
||||||
|
* the views are drawn on screen (e.g., default start page).</p>
|
||||||
|
*
|
||||||
|
* @param item
|
||||||
|
*/
|
||||||
|
public void setCurrentItem(int item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a page change listener which will receive forwarded events.
|
||||||
|
*
|
||||||
|
* @param listener
|
||||||
|
*/
|
||||||
|
public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify the indicator that the fragment list has changed.
|
||||||
|
*/
|
||||||
|
public void notifyDataSetChanged();
|
||||||
|
}
|
||||||
@ -0,0 +1,246 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011 The Android Open Source Project
|
||||||
|
* Copyright (C) 2011 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.
|
||||||
|
*/
|
||||||
|
package com.viewpagerindicator;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.v4.view.PagerAdapter;
|
||||||
|
import android.support.v4.view.ViewPager;
|
||||||
|
import android.support.v4.view.ViewPager.OnPageChangeListener;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.HorizontalScrollView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This widget implements the dynamic action bar tab behavior that can change
|
||||||
|
* across different configurations or circumstances.
|
||||||
|
*/
|
||||||
|
public class TabPageIndicator extends HorizontalScrollView implements PageIndicator {
|
||||||
|
Runnable mTabSelector;
|
||||||
|
|
||||||
|
private OnClickListener mTabClickListener = new OnClickListener() {
|
||||||
|
public void onClick(View view) {
|
||||||
|
TabView tabView = (TabView)view;
|
||||||
|
mViewPager.setCurrentItem(tabView.getIndex());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private LinearLayout mTabLayout;
|
||||||
|
private ViewPager mViewPager;
|
||||||
|
private ViewPager.OnPageChangeListener mListener;
|
||||||
|
|
||||||
|
private LayoutInflater mInflater;
|
||||||
|
|
||||||
|
int mMaxTabWidth;
|
||||||
|
private int mSelectedTabIndex;
|
||||||
|
|
||||||
|
public TabPageIndicator(Context context) {
|
||||||
|
this(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TabPageIndicator(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
setHorizontalScrollBarEnabled(false);
|
||||||
|
|
||||||
|
mInflater = LayoutInflater.from(context);
|
||||||
|
|
||||||
|
mTabLayout = new LinearLayout(getContext());
|
||||||
|
addView(mTabLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.FILL_PARENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
|
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||||
|
final boolean lockedExpanded = widthMode == MeasureSpec.EXACTLY;
|
||||||
|
setFillViewport(lockedExpanded);
|
||||||
|
|
||||||
|
final int childCount = mTabLayout.getChildCount();
|
||||||
|
if (childCount > 1 && (widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST)) {
|
||||||
|
if (childCount > 2) {
|
||||||
|
mMaxTabWidth = (int)(MeasureSpec.getSize(widthMeasureSpec) * 0.4f);
|
||||||
|
} else {
|
||||||
|
mMaxTabWidth = MeasureSpec.getSize(widthMeasureSpec) / 2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mMaxTabWidth = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int oldWidth = getMeasuredWidth();
|
||||||
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||||
|
final int newWidth = getMeasuredWidth();
|
||||||
|
|
||||||
|
if (lockedExpanded && oldWidth != newWidth) {
|
||||||
|
// Recenter the tab display if we're at a new (scrollable) size.
|
||||||
|
setCurrentItem(mSelectedTabIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void animateToTab(final int position) {
|
||||||
|
final View tabView = mTabLayout.getChildAt(position);
|
||||||
|
if (mTabSelector != null) {
|
||||||
|
removeCallbacks(mTabSelector);
|
||||||
|
}
|
||||||
|
mTabSelector = new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
final int scrollPos = tabView.getLeft() - (getWidth() - tabView.getWidth()) / 2;
|
||||||
|
smoothScrollTo(scrollPos, 0);
|
||||||
|
mTabSelector = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
post(mTabSelector);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttachedToWindow() {
|
||||||
|
super.onAttachedToWindow();
|
||||||
|
if (mTabSelector != null) {
|
||||||
|
// Re-post the selector we saved
|
||||||
|
post(mTabSelector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDetachedFromWindow() {
|
||||||
|
super.onDetachedFromWindow();
|
||||||
|
if (mTabSelector != null) {
|
||||||
|
removeCallbacks(mTabSelector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addTab(String text, int index) {
|
||||||
|
//Workaround for not being able to pass a defStyle on pre-3.0
|
||||||
|
final TabView tabView = (TabView)mInflater.inflate(R.layout.vpi__tab, null);
|
||||||
|
tabView.init(this, text, index);
|
||||||
|
tabView.setFocusable(true);
|
||||||
|
tabView.setOnClickListener(mTabClickListener);
|
||||||
|
|
||||||
|
mTabLayout.addView(tabView, new LinearLayout.LayoutParams(0, LayoutParams.FILL_PARENT, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPageScrollStateChanged(int arg0) {
|
||||||
|
if (mListener != null) {
|
||||||
|
mListener.onPageScrollStateChanged(arg0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPageScrolled(int arg0, float arg1, int arg2) {
|
||||||
|
if (mListener != null) {
|
||||||
|
mListener.onPageScrolled(arg0, arg1, arg2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPageSelected(int arg0) {
|
||||||
|
setCurrentItem(arg0);
|
||||||
|
if (mListener != null) {
|
||||||
|
mListener.onPageSelected(arg0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setViewPager(ViewPager view) {
|
||||||
|
final PagerAdapter adapter = view.getAdapter();
|
||||||
|
if (adapter == null) {
|
||||||
|
throw new IllegalStateException("ViewPager does not have adapter instance.");
|
||||||
|
}
|
||||||
|
if (!(adapter instanceof TitleProvider)) {
|
||||||
|
throw new IllegalStateException("ViewPager adapter must implement TitleProvider to be used with TitlePageIndicator.");
|
||||||
|
}
|
||||||
|
mViewPager = view;
|
||||||
|
view.setOnPageChangeListener(this);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void notifyDataSetChanged() {
|
||||||
|
mTabLayout.removeAllViews();
|
||||||
|
TitleProvider adapter = (TitleProvider)mViewPager.getAdapter();
|
||||||
|
final int count = ((PagerAdapter)adapter).getCount();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
addTab(adapter.getTitle(i), i);
|
||||||
|
}
|
||||||
|
if (mSelectedTabIndex > count) {
|
||||||
|
mSelectedTabIndex = count - 1;
|
||||||
|
}
|
||||||
|
setCurrentItem(mSelectedTabIndex);
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@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.");
|
||||||
|
}
|
||||||
|
mSelectedTabIndex = item;
|
||||||
|
final int tabCount = mTabLayout.getChildCount();
|
||||||
|
for (int i = 0; i < tabCount; i++) {
|
||||||
|
final View child = mTabLayout.getChildAt(i);
|
||||||
|
final boolean isSelected = (i == item);
|
||||||
|
child.setSelected(isSelected);
|
||||||
|
if (isSelected) {
|
||||||
|
animateToTab(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOnPageChangeListener(OnPageChangeListener listener) {
|
||||||
|
mListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TabView extends LinearLayout {
|
||||||
|
private TabPageIndicator mParent;
|
||||||
|
private int mIndex;
|
||||||
|
|
||||||
|
public TabView(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(TabPageIndicator parent, String text, int index) {
|
||||||
|
mParent = parent;
|
||||||
|
mIndex = index;
|
||||||
|
|
||||||
|
TextView textView = (TextView)findViewById(android.R.id.text1);
|
||||||
|
textView.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||||
|
|
||||||
|
// Re-measure if we went beyond our maximum size.
|
||||||
|
if (mParent.mMaxTabWidth > 0 && getMeasuredWidth() > mParent.mMaxTabWidth) {
|
||||||
|
super.onMeasure(MeasureSpec.makeMeasureSpec(mParent.mMaxTabWidth, MeasureSpec.EXACTLY),
|
||||||
|
heightMeasureSpec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIndex() {
|
||||||
|
return mIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,776 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011 Jake Wharton
|
||||||
|
* Copyright (C) 2011 Patrik Akerfeldt
|
||||||
|
* Copyright (C) 2011 Francisco Figueiredo Jr.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
package com.viewpagerindicator;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Path;
|
||||||
|
import android.graphics.RectF;
|
||||||
|
import android.graphics.Typeface;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
import android.support.v4.view.MotionEventCompat;
|
||||||
|
import android.support.v4.view.PagerAdapter;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A TitlePageIndicator is a PageIndicator which displays the title of left view
|
||||||
|
* (if exist), the title of the current select view (centered) and the title of
|
||||||
|
* the right view (if exist). When the user scrolls the ViewPager then titles are
|
||||||
|
* also scrolled.
|
||||||
|
*/
|
||||||
|
public class TitlePageIndicator extends View implements PageIndicator {
|
||||||
|
/**
|
||||||
|
* Percentage indicating what percentage of the screen width away from
|
||||||
|
* center should the underline be fully faded. A value of 0.25 means that
|
||||||
|
* halfway between the center of the screen and an edge.
|
||||||
|
*/
|
||||||
|
private static final float SELECTION_FADE_PERCENTAGE = 0.25f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Percentage indicating what percentage of the screen width away from
|
||||||
|
* center should the selected text bold turn off. A value of 0.05 means
|
||||||
|
* that 10% between the center and an edge.
|
||||||
|
*/
|
||||||
|
private static final float BOLD_FADE_PERCENTAGE = 0.05f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for a callback when the center item has been clicked.
|
||||||
|
*/
|
||||||
|
public static interface OnCenterItemClickListener {
|
||||||
|
/**
|
||||||
|
* Callback when the center item has been clicked.
|
||||||
|
*
|
||||||
|
* @param position Position of the current center item.
|
||||||
|
*/
|
||||||
|
public void onCenterItemClick(int position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum IndicatorStyle {
|
||||||
|
None(0), Triangle(1), Underline(2);
|
||||||
|
|
||||||
|
public final int value;
|
||||||
|
|
||||||
|
private IndicatorStyle(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IndicatorStyle fromValue(int value) {
|
||||||
|
for (IndicatorStyle style : IndicatorStyle.values()) {
|
||||||
|
if (style.value == value) {
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ViewPager mViewPager;
|
||||||
|
private ViewPager.OnPageChangeListener mListener;
|
||||||
|
private TitleProvider mTitleProvider;
|
||||||
|
private int mCurrentPage;
|
||||||
|
private int mCurrentOffset;
|
||||||
|
private int mScrollState;
|
||||||
|
private final Paint mPaintText = new Paint();
|
||||||
|
private boolean mBoldText;
|
||||||
|
private int mColorText;
|
||||||
|
private int mColorSelected;
|
||||||
|
private Path mPath;
|
||||||
|
private final Paint mPaintFooterLine = new Paint();
|
||||||
|
private IndicatorStyle mFooterIndicatorStyle;
|
||||||
|
private final Paint mPaintFooterIndicator = new Paint();
|
||||||
|
private float mFooterIndicatorHeight;
|
||||||
|
private float mFooterIndicatorUnderlinePadding;
|
||||||
|
private float mFooterPadding;
|
||||||
|
private float mTitlePadding;
|
||||||
|
private float mTopPadding;
|
||||||
|
/** Left and right side padding for not active view titles. */
|
||||||
|
private float mClipPadding;
|
||||||
|
private float mFooterLineHeight;
|
||||||
|
|
||||||
|
private static final int INVALID_POINTER = -1;
|
||||||
|
|
||||||
|
private int mTouchSlop;
|
||||||
|
private float mLastMotionX = -1;
|
||||||
|
private int mActivePointerId = INVALID_POINTER;
|
||||||
|
private boolean mIsDragging;
|
||||||
|
|
||||||
|
private OnCenterItemClickListener mCenterItemClickListener;
|
||||||
|
|
||||||
|
|
||||||
|
public TitlePageIndicator(Context context) {
|
||||||
|
this(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TitlePageIndicator(Context context, AttributeSet attrs) {
|
||||||
|
this(context, attrs, R.attr.vpiTitlePageIndicatorStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TitlePageIndicator(Context context, AttributeSet attrs, int defStyle) {
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
|
||||||
|
//Load defaults from resources
|
||||||
|
final Resources res = getResources();
|
||||||
|
final int defaultFooterColor = res.getColor(R.color.default_title_indicator_footer_color);
|
||||||
|
final float defaultFooterLineHeight = res.getDimension(R.dimen.default_title_indicator_footer_line_height);
|
||||||
|
final int defaultFooterIndicatorStyle = res.getInteger(R.integer.default_title_indicator_footer_indicator_style);
|
||||||
|
final float defaultFooterIndicatorHeight = res.getDimension(R.dimen.default_title_indicator_footer_indicator_height);
|
||||||
|
final float defaultFooterIndicatorUnderlinePadding = res.getDimension(R.dimen.default_title_indicator_footer_indicator_underline_padding);
|
||||||
|
final float defaultFooterPadding = res.getDimension(R.dimen.default_title_indicator_footer_padding);
|
||||||
|
final int defaultSelectedColor = res.getColor(R.color.default_title_indicator_selected_color);
|
||||||
|
final boolean defaultSelectedBold = res.getBoolean(R.bool.default_title_indicator_selected_bold);
|
||||||
|
final int defaultTextColor = res.getColor(R.color.default_title_indicator_text_color);
|
||||||
|
final float defaultTextSize = res.getDimension(R.dimen.default_title_indicator_text_size);
|
||||||
|
final float defaultTitlePadding = res.getDimension(R.dimen.default_title_indicator_title_padding);
|
||||||
|
final float defaultClipPadding = res.getDimension(R.dimen.default_title_indicator_clip_padding);
|
||||||
|
final float defaultTopPadding = res.getDimension(R.dimen.default_title_indicator_top_padding);
|
||||||
|
|
||||||
|
//Retrieve styles attributes
|
||||||
|
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TitlePageIndicator, defStyle, R.style.Widget_TitlePageIndicator);
|
||||||
|
|
||||||
|
//Retrieve the colors to be used for this view and apply them.
|
||||||
|
mFooterLineHeight = a.getDimension(R.styleable.TitlePageIndicator_footerLineHeight, defaultFooterLineHeight);
|
||||||
|
mFooterIndicatorStyle = IndicatorStyle.fromValue(a.getInteger(R.styleable.TitlePageIndicator_footerIndicatorStyle, defaultFooterIndicatorStyle));
|
||||||
|
mFooterIndicatorHeight = a.getDimension(R.styleable.TitlePageIndicator_footerIndicatorHeight, defaultFooterIndicatorHeight);
|
||||||
|
mFooterIndicatorUnderlinePadding = a.getDimension(R.styleable.TitlePageIndicator_footerIndicatorUnderlinePadding, defaultFooterIndicatorUnderlinePadding);
|
||||||
|
mFooterPadding = a.getDimension(R.styleable.TitlePageIndicator_footerPadding, defaultFooterPadding);
|
||||||
|
mTopPadding = a.getDimension(R.styleable.TitlePageIndicator_topPadding, defaultTopPadding);
|
||||||
|
mTitlePadding = a.getDimension(R.styleable.TitlePageIndicator_titlePadding, defaultTitlePadding);
|
||||||
|
mClipPadding = a.getDimension(R.styleable.TitlePageIndicator_clipPadding, defaultClipPadding);
|
||||||
|
mColorSelected = a.getColor(R.styleable.TitlePageIndicator_selectedColor, defaultSelectedColor);
|
||||||
|
mColorText = a.getColor(R.styleable.TitlePageIndicator_textColor, defaultTextColor);
|
||||||
|
mBoldText = a.getBoolean(R.styleable.TitlePageIndicator_selectedBold, defaultSelectedBold);
|
||||||
|
|
||||||
|
final float textSize = a.getDimension(R.styleable.TitlePageIndicator_textSize, defaultTextSize);
|
||||||
|
final int footerColor = a.getColor(R.styleable.TitlePageIndicator_footerColor, defaultFooterColor);
|
||||||
|
mPaintText.setTextSize(textSize);
|
||||||
|
mPaintText.setAntiAlias(true);
|
||||||
|
mPaintFooterLine.setStyle(Paint.Style.FILL_AND_STROKE);
|
||||||
|
mPaintFooterLine.setStrokeWidth(mFooterLineHeight);
|
||||||
|
mPaintFooterLine.setColor(footerColor);
|
||||||
|
mPaintFooterIndicator.setStyle(Paint.Style.FILL_AND_STROKE);
|
||||||
|
mPaintFooterIndicator.setColor(footerColor);
|
||||||
|
|
||||||
|
a.recycle();
|
||||||
|
|
||||||
|
final ViewConfiguration configuration = ViewConfiguration.get(context);
|
||||||
|
mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int getFooterColor() {
|
||||||
|
return mPaintFooterLine.getColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFooterColor(int footerColor) {
|
||||||
|
mPaintFooterLine.setColor(footerColor);
|
||||||
|
mPaintFooterIndicator.setColor(footerColor);
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getFooterLineHeight() {
|
||||||
|
return mFooterLineHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFooterLineHeight(float footerLineHeight) {
|
||||||
|
mFooterLineHeight = footerLineHeight;
|
||||||
|
mPaintFooterLine.setStrokeWidth(mFooterLineHeight);
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getFooterIndicatorHeight() {
|
||||||
|
return mFooterIndicatorHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFooterIndicatorHeight(float footerTriangleHeight) {
|
||||||
|
mFooterIndicatorHeight = footerTriangleHeight;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getFooterIndicatorPadding() {
|
||||||
|
return mFooterPadding;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFooterIndicatorPadding(float footerIndicatorPadding) {
|
||||||
|
mFooterPadding = footerIndicatorPadding;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndicatorStyle getFooterIndicatorStyle() {
|
||||||
|
return mFooterIndicatorStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFooterIndicatorStyle(IndicatorStyle indicatorStyle) {
|
||||||
|
mFooterIndicatorStyle = indicatorStyle;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSelectedColor() {
|
||||||
|
return mColorSelected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectedColor(int selectedColor) {
|
||||||
|
mColorSelected = selectedColor;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSelectedBold() {
|
||||||
|
return mBoldText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectedBold(boolean selectedBold) {
|
||||||
|
mBoldText = selectedBold;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTextColor() {
|
||||||
|
return mColorText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTextColor(int textColor) {
|
||||||
|
mPaintText.setColor(textColor);
|
||||||
|
mColorText = textColor;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getTextSize() {
|
||||||
|
return mPaintText.getTextSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTextSize(float textSize) {
|
||||||
|
mPaintText.setTextSize(textSize);
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getTitlePadding() {
|
||||||
|
return this.mTitlePadding;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitlePadding(float titlePadding) {
|
||||||
|
mTitlePadding = titlePadding;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getTopPadding() {
|
||||||
|
return this.mTopPadding;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTopPadding(float topPadding) {
|
||||||
|
mTopPadding = topPadding;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getClipPadding() {
|
||||||
|
return this.mClipPadding;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClipPadding(float clipPadding) {
|
||||||
|
mClipPadding = clipPadding;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTypeface(Typeface typeface) {
|
||||||
|
mPaintText.setTypeface(typeface);
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Typeface getTypeface() {
|
||||||
|
return mPaintText.getTypeface();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see android.view.View#onDraw(android.graphics.Canvas)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void onDraw(Canvas canvas) {
|
||||||
|
super.onDraw(canvas);
|
||||||
|
|
||||||
|
if (mViewPager == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final int count = mViewPager.getAdapter().getCount();
|
||||||
|
if (count == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Calculate views bounds
|
||||||
|
ArrayList<RectF> bounds = calculateAllBounds(mPaintText);
|
||||||
|
|
||||||
|
//Make sure we're on a page that still exists
|
||||||
|
if (mCurrentPage >= bounds.size()) {
|
||||||
|
setCurrentItem(bounds.size()-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
final int countMinusOne = count - 1;
|
||||||
|
final float halfWidth = getWidth() / 2f;
|
||||||
|
final int left = getLeft();
|
||||||
|
final float leftClip = left + mClipPadding;
|
||||||
|
final int width = getWidth();
|
||||||
|
final int height = getHeight();
|
||||||
|
final int right = left + width;
|
||||||
|
final float rightClip = right - mClipPadding;
|
||||||
|
|
||||||
|
int page = mCurrentPage;
|
||||||
|
float offsetPercent;
|
||||||
|
if (mCurrentOffset <= halfWidth) {
|
||||||
|
offsetPercent = 1.0f * mCurrentOffset / width;
|
||||||
|
} else {
|
||||||
|
page += 1;
|
||||||
|
offsetPercent = 1.0f * (width - mCurrentOffset) / width;
|
||||||
|
}
|
||||||
|
final boolean currentSelected = (offsetPercent <= SELECTION_FADE_PERCENTAGE);
|
||||||
|
final boolean currentBold = (offsetPercent <= BOLD_FADE_PERCENTAGE);
|
||||||
|
final float selectedPercent = (SELECTION_FADE_PERCENTAGE - offsetPercent) / SELECTION_FADE_PERCENTAGE;
|
||||||
|
|
||||||
|
//Verify if the current view must be clipped to the screen
|
||||||
|
RectF curPageBound = bounds.get(mCurrentPage);
|
||||||
|
float curPageWidth = curPageBound.right - curPageBound.left;
|
||||||
|
if (curPageBound.left < leftClip) {
|
||||||
|
//Try to clip to the screen (left side)
|
||||||
|
clipViewOnTheLeft(curPageBound, curPageWidth, left);
|
||||||
|
}
|
||||||
|
if (curPageBound.right > rightClip) {
|
||||||
|
//Try to clip to the screen (right side)
|
||||||
|
clipViewOnTheRight(curPageBound, curPageWidth, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Left views starting from the current position
|
||||||
|
if (mCurrentPage > 0) {
|
||||||
|
for (int i = mCurrentPage - 1; i >= 0; i--) {
|
||||||
|
RectF bound = bounds.get(i);
|
||||||
|
//Is left side is outside the screen
|
||||||
|
if (bound.left < leftClip) {
|
||||||
|
float w = bound.right - bound.left;
|
||||||
|
//Try to clip to the screen (left side)
|
||||||
|
clipViewOnTheLeft(bound, w, left);
|
||||||
|
//Except if there's an intersection with the right view
|
||||||
|
RectF rightBound = bounds.get(i + 1);
|
||||||
|
//Intersection
|
||||||
|
if (bound.right + mTitlePadding > rightBound.left) {
|
||||||
|
bound.left = rightBound.left - w - mTitlePadding;
|
||||||
|
bound.right = bound.left + w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Right views starting from the current position
|
||||||
|
if (mCurrentPage < countMinusOne) {
|
||||||
|
for (int i = mCurrentPage + 1 ; i < count; i++) {
|
||||||
|
RectF bound = bounds.get(i);
|
||||||
|
//If right side is outside the screen
|
||||||
|
if (bound.right > rightClip) {
|
||||||
|
float w = bound.right - bound.left;
|
||||||
|
//Try to clip to the screen (right side)
|
||||||
|
clipViewOnTheRight(bound, w, right);
|
||||||
|
//Except if there's an intersection with the left view
|
||||||
|
RectF leftBound = bounds.get(i - 1);
|
||||||
|
//Intersection
|
||||||
|
if (bound.left - mTitlePadding < leftBound.right) {
|
||||||
|
bound.left = leftBound.right + mTitlePadding;
|
||||||
|
bound.right = bound.left + w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Now draw views
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
//Get the title
|
||||||
|
RectF bound = bounds.get(i);
|
||||||
|
//Only if one side is visible
|
||||||
|
if ((bound.left > left && bound.left < right) || (bound.right > left && bound.right < right)) {
|
||||||
|
final boolean currentPage = (i == page);
|
||||||
|
//Only set bold if we are within bounds
|
||||||
|
mPaintText.setFakeBoldText(currentPage && currentBold && mBoldText);
|
||||||
|
|
||||||
|
//Draw text as unselected
|
||||||
|
mPaintText.setColor(mColorText);
|
||||||
|
canvas.drawText(mTitleProvider.getTitle(i), bound.left, bound.bottom + mTopPadding, mPaintText);
|
||||||
|
|
||||||
|
//If we are within the selected bounds draw the selected text
|
||||||
|
if (currentPage && currentSelected) {
|
||||||
|
mPaintText.setColor(mColorSelected);
|
||||||
|
mPaintText.setAlpha((int)((mColorSelected >>> 24) * selectedPercent));
|
||||||
|
canvas.drawText(mTitleProvider.getTitle(i), bound.left, bound.bottom + mTopPadding, mPaintText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Draw the footer line
|
||||||
|
mPath = new Path();
|
||||||
|
mPath.moveTo(0, height - mFooterLineHeight / 2f);
|
||||||
|
mPath.lineTo(width, height - mFooterLineHeight / 2f);
|
||||||
|
mPath.close();
|
||||||
|
canvas.drawPath(mPath, mPaintFooterLine);
|
||||||
|
|
||||||
|
switch (mFooterIndicatorStyle) {
|
||||||
|
case Triangle:
|
||||||
|
mPath = new Path();
|
||||||
|
mPath.moveTo(halfWidth, height - mFooterLineHeight - mFooterIndicatorHeight);
|
||||||
|
mPath.lineTo(halfWidth + mFooterIndicatorHeight, height - mFooterLineHeight);
|
||||||
|
mPath.lineTo(halfWidth - mFooterIndicatorHeight, height - mFooterLineHeight);
|
||||||
|
mPath.close();
|
||||||
|
canvas.drawPath(mPath, mPaintFooterIndicator);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Underline:
|
||||||
|
if (!currentSelected) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
RectF underlineBounds = bounds.get(page);
|
||||||
|
mPath = new Path();
|
||||||
|
mPath.moveTo(underlineBounds.left - mFooterIndicatorUnderlinePadding, height - mFooterLineHeight);
|
||||||
|
mPath.lineTo(underlineBounds.right + mFooterIndicatorUnderlinePadding, height - mFooterLineHeight);
|
||||||
|
mPath.lineTo(underlineBounds.right + mFooterIndicatorUnderlinePadding, height - mFooterLineHeight - mFooterIndicatorHeight);
|
||||||
|
mPath.lineTo(underlineBounds.left - mFooterIndicatorUnderlinePadding, height - mFooterLineHeight - mFooterIndicatorHeight);
|
||||||
|
mPath.close();
|
||||||
|
|
||||||
|
mPaintFooterIndicator.setAlpha((int)(0xFF * selectedPercent));
|
||||||
|
canvas.drawPath(mPath, mPaintFooterIndicator);
|
||||||
|
mPaintFooterIndicator.setAlpha(0xFF);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onTouchEvent(android.view.MotionEvent ev) {
|
||||||
|
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) {
|
||||||
|
if (!mViewPager.isFakeDragging()) {
|
||||||
|
mViewPager.beginFakeDrag();
|
||||||
|
}
|
||||||
|
|
||||||
|
mLastMotionX = x;
|
||||||
|
|
||||||
|
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;
|
||||||
|
final float leftThird = halfWidth - sixthWidth;
|
||||||
|
final float rightThird = halfWidth + sixthWidth;
|
||||||
|
final float eventX = ev.getX();
|
||||||
|
|
||||||
|
if (eventX < leftThird) {
|
||||||
|
if (mCurrentPage > 0) {
|
||||||
|
mViewPager.setCurrentItem(mCurrentPage - 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (eventX > rightThird) {
|
||||||
|
if (mCurrentPage < count - 1) {
|
||||||
|
mViewPager.setCurrentItem(mCurrentPage + 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Middle third
|
||||||
|
if (mCenterItemClickListener != null) {
|
||||||
|
mCenterItemClickListener.onCenterItemClick(mCurrentPage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set bounds for the right textView including clip padding.
|
||||||
|
*
|
||||||
|
* @param curViewBound
|
||||||
|
* current bounds.
|
||||||
|
* @param curViewWidth
|
||||||
|
* width of the view.
|
||||||
|
*/
|
||||||
|
private void clipViewOnTheRight(RectF curViewBound, float curViewWidth, int right) {
|
||||||
|
curViewBound.right = right - mClipPadding;
|
||||||
|
curViewBound.left = curViewBound.right - curViewWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set bounds for the left textView including clip padding.
|
||||||
|
*
|
||||||
|
* @param curViewBound
|
||||||
|
* current bounds.
|
||||||
|
* @param curViewWidth
|
||||||
|
* width of the view.
|
||||||
|
*/
|
||||||
|
private void clipViewOnTheLeft(RectF curViewBound, float curViewWidth, int left) {
|
||||||
|
curViewBound.left = left + mClipPadding;
|
||||||
|
curViewBound.right = mClipPadding + curViewWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate views bounds and scroll them according to the current index
|
||||||
|
*
|
||||||
|
* @param paint
|
||||||
|
* @param currentIndex
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private ArrayList<RectF> calculateAllBounds(Paint paint) {
|
||||||
|
ArrayList<RectF> list = new ArrayList<RectF>();
|
||||||
|
//For each views (If no values then add a fake one)
|
||||||
|
final int count = mViewPager.getAdapter().getCount();
|
||||||
|
final int width = getWidth();
|
||||||
|
final int halfWidth = width / 2;
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
RectF bounds = calcBounds(i, paint);
|
||||||
|
float w = (bounds.right - bounds.left);
|
||||||
|
float h = (bounds.bottom - bounds.top);
|
||||||
|
bounds.left = (halfWidth) - (w / 2) - mCurrentOffset + ((i - mCurrentPage) * width);
|
||||||
|
bounds.right = bounds.left + w;
|
||||||
|
bounds.top = 0;
|
||||||
|
bounds.bottom = h;
|
||||||
|
list.add(bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the bounds for a view's title
|
||||||
|
*
|
||||||
|
* @param index
|
||||||
|
* @param paint
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private RectF calcBounds(int index, Paint paint) {
|
||||||
|
//Calculate the text bounds
|
||||||
|
RectF bounds = new RectF();
|
||||||
|
bounds.right = paint.measureText(mTitleProvider.getTitle(index));
|
||||||
|
bounds.bottom = paint.descent() - paint.ascent();
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setViewPager(ViewPager view) {
|
||||||
|
final PagerAdapter adapter = view.getAdapter();
|
||||||
|
if (adapter == null) {
|
||||||
|
throw new IllegalStateException("ViewPager does not have adapter instance.");
|
||||||
|
}
|
||||||
|
if (!(adapter instanceof TitleProvider)) {
|
||||||
|
throw new IllegalStateException("ViewPager adapter must implement TitleProvider to be used with TitlePageIndicator.");
|
||||||
|
}
|
||||||
|
mViewPager = view;
|
||||||
|
mViewPager.setOnPageChangeListener(this);
|
||||||
|
mTitleProvider = (TitleProvider)adapter;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setViewPager(ViewPager view, int initialPosition) {
|
||||||
|
setViewPager(view);
|
||||||
|
setCurrentItem(initialPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyDataSetChanged() {
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a callback listener for the center item click.
|
||||||
|
*
|
||||||
|
* @param listener Callback instance.
|
||||||
|
*/
|
||||||
|
public void setOnCenterItemClickListener(OnCenterItemClickListener listener) {
|
||||||
|
mCenterItemClickListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 onPageScrollStateChanged(int state) {
|
||||||
|
mScrollState = state;
|
||||||
|
|
||||||
|
if (mListener != null) {
|
||||||
|
mListener.onPageScrollStateChanged(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||||
|
mCurrentPage = position;
|
||||||
|
mCurrentOffset = positionOffsetPixels;
|
||||||
|
invalidate();
|
||||||
|
|
||||||
|
if (mListener != null) {
|
||||||
|
mListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPageSelected(int position) {
|
||||||
|
if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
|
||||||
|
mCurrentPage = position;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mListener != null) {
|
||||||
|
mListener.onPageSelected(position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
|
||||||
|
mListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
|
//Measure our width in whatever mode specified
|
||||||
|
final int measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
|
||||||
|
|
||||||
|
//Determine our height
|
||||||
|
float height = 0;
|
||||||
|
final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||||
|
if (heightSpecMode == MeasureSpec.EXACTLY) {
|
||||||
|
//We were told how big to be
|
||||||
|
height = MeasureSpec.getSize(heightMeasureSpec);
|
||||||
|
} else {
|
||||||
|
//Calculate the text bounds
|
||||||
|
RectF bounds = new RectF();
|
||||||
|
bounds.bottom = mPaintText.descent()-mPaintText.ascent();
|
||||||
|
height = bounds.bottom - bounds.top + mFooterLineHeight + mFooterPadding + mTopPadding;
|
||||||
|
if (mFooterIndicatorStyle != IndicatorStyle.None) {
|
||||||
|
height += mFooterIndicatorHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final int measuredHeight = (int)height;
|
||||||
|
|
||||||
|
setMeasuredDimension(measuredWidth, measuredHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
|
||||||
|
@Override
|
||||||
|
public SavedState createFromParcel(Parcel in) {
|
||||||
|
return new SavedState(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SavedState[] newArray(int size) {
|
||||||
|
return new SavedState[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011 Patrik Akerfeldt
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
package com.viewpagerindicator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A TitleProvider provides the title to display according to a view.
|
||||||
|
*/
|
||||||
|
public interface TitleProvider {
|
||||||
|
/**
|
||||||
|
* Returns the title of the view at position
|
||||||
|
* @param position
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getTitle(int position);
|
||||||
|
}
|
||||||
@ -0,0 +1,171 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.viewpagerindicator</groupId>
|
||||||
|
<artifactId>parent</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<version>2.2.2</version>
|
||||||
|
|
||||||
|
<name>Android-ViewPagerIndicator (Parent)</name>
|
||||||
|
<description>Android library for.</description>
|
||||||
|
<url>https://github.com/JakeWharton/Android-ViewPagerIndicator</url>
|
||||||
|
<inceptionYear>2011</inceptionYear>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>library</module>
|
||||||
|
<module>sample</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
|
<scm>
|
||||||
|
<url>http://github.com/JakeWharton/Android-ViewPagerIndicator/</url>
|
||||||
|
<connection>scm:git:git://github.com/JakeWharton/Android-ViewPagerIndicator.git</connection>
|
||||||
|
<developerConnection>scm:git:git@github.com:JakeWharton/Android-ViewPagerIndicator.git</developerConnection>
|
||||||
|
</scm>
|
||||||
|
|
||||||
|
<developers>
|
||||||
|
<developer>
|
||||||
|
<name>Jake Wharton</name>
|
||||||
|
<email>jakewharton@gmail.com</email>
|
||||||
|
<id>jakewharton</id>
|
||||||
|
<url>http://jakewharton.com</url>
|
||||||
|
<timezone>-5</timezone>
|
||||||
|
<roles>
|
||||||
|
<role>developer</role>
|
||||||
|
</roles>
|
||||||
|
</developer>
|
||||||
|
</developers>
|
||||||
|
|
||||||
|
<licenses>
|
||||||
|
<license>
|
||||||
|
<name>Apache License Version 2.0</name>
|
||||||
|
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||||
|
<distribution>repo</distribution>
|
||||||
|
</license>
|
||||||
|
</licenses>
|
||||||
|
|
||||||
|
<distributionManagement>
|
||||||
|
<repository>
|
||||||
|
<id>personal-repository</id>
|
||||||
|
<name>JakeWharton.com Maven Repository</name>
|
||||||
|
<url>scp://r.jakewharton.com/home/jakewharton_repository/r.jakewharton.com/maven/release/</url>
|
||||||
|
</repository>
|
||||||
|
<snapshotRepository>
|
||||||
|
<id>personal-repository</id>
|
||||||
|
<name>JakeWharton.com Maven Repository</name>
|
||||||
|
<url>scp://r.jakewharton.com/home/jakewharton_repository/r.jakewharton.com/maven/snapshot/</url>
|
||||||
|
</snapshotRepository>
|
||||||
|
</distributionManagement>
|
||||||
|
|
||||||
|
<organization>
|
||||||
|
<name>Jake Wharton</name>
|
||||||
|
<url>http://jakewharton.com</url>
|
||||||
|
</organization>
|
||||||
|
|
||||||
|
<issueManagement>
|
||||||
|
<system>GitHub Issues</system>
|
||||||
|
<url>https://github.com/JakeWharton/Android-ViewPagerIndicator/issues</url>
|
||||||
|
</issueManagement>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
|
|
||||||
|
<java.version>1.6</java.version>
|
||||||
|
<android.version>1.6_r3</android.version>
|
||||||
|
<android.platform>4</android.platform>
|
||||||
|
<android.support.version>r6</android.support.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>android</groupId>
|
||||||
|
<artifactId>android</artifactId>
|
||||||
|
<version>${android.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>android.support</groupId>
|
||||||
|
<artifactId>compatibility-v4</artifactId>
|
||||||
|
<version>${android.support.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>com.jakewharton</id>
|
||||||
|
<url>http://r.jakewharton.com/maven/release</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>2.3.2</version>
|
||||||
|
<configuration>
|
||||||
|
<source>${java.version}</source>
|
||||||
|
<target>${java.version}</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<version>2.8</version>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
|
||||||
|
<artifactId>android-maven-plugin</artifactId>
|
||||||
|
<version>3.0.0-alpha-13</version>
|
||||||
|
<configuration>
|
||||||
|
<sdk>
|
||||||
|
<platform>${android.platform}</platform>
|
||||||
|
</sdk>
|
||||||
|
<undeployBeforeDeploy>true</undeployBeforeDeploy>
|
||||||
|
</configuration>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||||
|
<version>2.6</version>
|
||||||
|
<configuration>
|
||||||
|
<failsOnError>true</failsOnError>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-release-plugin</artifactId>
|
||||||
|
<version>2.1</version>
|
||||||
|
<configuration>
|
||||||
|
<autoVersionSubmodules>true</autoVersionSubmodules>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-deploy-plugin</artifactId>
|
||||||
|
<version>2.6</version>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven.wagon</groupId>
|
||||||
|
<artifactId>wagon-ssh</artifactId>
|
||||||
|
<version>1.0-beta-7</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||