Related
I am using swipe refresh layout but it is not working for web view. It is working for a simple activity layout, but when i am using a web view it's not working properly.
Here is my code.
public class SwipeActivity extends Activity implements OnRefreshListener{
SwipeRefreshLayout swipeLayout;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_swipe);
swipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
swipeLayout.setOnRefreshListener(this);
swipeLayout.setColorScheme(android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light,
android.R.color.holo_red_light);
}
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
#Override public void run() {
swipeLayout.setRefreshing(false);
}
}, 5000);
}
}
And this one is swipe refresh layout.
public class SwipeRefreshLayout extends ViewGroup {
private static final long RETURN_TO_ORIGINAL_POSITION_TIMEOUT = 300;
private static final float ACCELERATE_INTERPOLATION_FACTOR = 1.5f;
private static final float DECELERATE_INTERPOLATION_FACTOR = 2f;
private static final float PROGRESS_BAR_HEIGHT = 4;
private static final float MAX_SWIPE_DISTANCE_FACTOR = .6f;
private static final int REFRESH_TRIGGER_DISTANCE = 120;
private SwipeProgressBar mProgressBar; //the thing that shows progress is going
private View mTarget; //the content that gets pulled down
private int mOriginalOffsetTop;
private OnRefreshListener mListener;
private MotionEvent mDownEvent;
private int mFrom;
private boolean mRefreshing = false;
private int mTouchSlop;
private float mDistanceToTriggerSync = -1;
private float mPrevY;
private int mMediumAnimationDuration;
private float mFromPercentage = 0;
private float mCurrPercentage = 0;
private int mProgressBarHeight;
private int mCurrentTargetOffsetTop;
// Target is returning to its start offset because it was cancelled or a
// refresh was triggered.
private boolean mReturningToStart;
private final DecelerateInterpolator mDecelerateInterpolator;
private final AccelerateInterpolator mAccelerateInterpolator;
private static final int[] LAYOUT_ATTRS = new int[] {
android.R.attr.enabled
};
private final Animation mAnimateToStartPosition = new Animation() {
#Override
public void applyTransformation(float interpolatedTime, Transformation t) {
int targetTop = 0;
if (mFrom != mOriginalOffsetTop) {
targetTop = (mFrom + (int)((mOriginalOffsetTop - mFrom) * interpolatedTime));
}
int offset = targetTop - mTarget.getTop();
final int currentTop = mTarget.getTop();
if (offset + currentTop < 0) {
offset = 0 - currentTop;
}
setTargetOffsetTopAndBottom(offset);
}
};
private Animation mShrinkTrigger = new Animation() {
#Override
public void applyTransformation(float interpolatedTime, Transformation t) {
float percent = mFromPercentage + ((0 - mFromPercentage) * interpolatedTime);
mProgressBar.setTriggerPercentage(percent);
}
};
private final AnimationListener mReturnToStartPositionListener = new BaseAnimationListener() {
#Override
public void onAnimationEnd(Animation animation) {
// Once the target content has returned to its start position, reset
// the target offset to 0
mCurrentTargetOffsetTop = 0;
}
};
private final AnimationListener mShrinkAnimationListener = new BaseAnimationListener() {
#Override
public void onAnimationEnd(Animation animation) {
mCurrPercentage = 0;
}
};
private final Runnable mReturnToStartPosition = new Runnable() {
#Override
public void run() {
mReturningToStart = true;
animateOffsetToStartPosition(mCurrentTargetOffsetTop + getPaddingTop(),
mReturnToStartPositionListener);
}
};
// Cancel the refresh gesture and animate everything back to its original state.
private final Runnable mCancel = new Runnable() {
#Override
public void run() {
mReturningToStart = true;
// Timeout fired since the user last moved their finger; animate the
// trigger to 0 and put the target back at its original position
if (mProgressBar != null) {
mFromPercentage = mCurrPercentage;
mShrinkTrigger.setDuration(mMediumAnimationDuration);
mShrinkTrigger.setAnimationListener(mShrinkAnimationListener);
mShrinkTrigger.reset();
mShrinkTrigger.setInterpolator(mDecelerateInterpolator);
startAnimation(mShrinkTrigger);
}
animateOffsetToStartPosition(mCurrentTargetOffsetTop + getPaddingTop(),
mReturnToStartPositionListener);
}
};
/**
* Simple constructor to use when creating a SwipeRefreshLayout from code.
* #param context
*/
public SwipeRefreshLayout(Context context) {
this(context, null);
}
/**
* Constructor that is called when inflating SwipeRefreshLayout from XML.
* #param context
* #param attrs
*/
public SwipeRefreshLayout(Context context, AttributeSet attrs) {
super(context, attrs);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mMediumAnimationDuration = getResources().getInteger(
android.R.integer.config_mediumAnimTime);
setWillNotDraw(false);
mProgressBar = new SwipeProgressBar(this);
final DisplayMetrics metrics = getResources().getDisplayMetrics();
mProgressBarHeight = (int) (metrics.density * PROGRESS_BAR_HEIGHT);
mDecelerateInterpolator = new DecelerateInterpolator(DECELERATE_INTERPOLATION_FACTOR);
mAccelerateInterpolator = new AccelerateInterpolator(ACCELERATE_INTERPOLATION_FACTOR);
final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS);
setEnabled(a.getBoolean(0, true));
a.recycle();
}
#Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
removeCallbacks(mCancel);
removeCallbacks(mReturnToStartPosition);
}
#Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
removeCallbacks(mReturnToStartPosition);
removeCallbacks(mCancel);
}
private void animateOffsetToStartPosition(int from, AnimationListener listener) {
mFrom = from;
mAnimateToStartPosition.reset();
mAnimateToStartPosition.setDuration(mMediumAnimationDuration);
mAnimateToStartPosition.setAnimationListener(listener);
mAnimateToStartPosition.setInterpolator(mDecelerateInterpolator);
mTarget.startAnimation(mAnimateToStartPosition);
}
/**
* Set the listener to be notified when a refresh is triggered via the swipe
* gesture.
*/
public void setOnRefreshListener(SwipeActivity swipeActivity) {
mListener = swipeActivity;
}
private void setTriggerPercentage(float percent) {
if (percent == 0f) {
// No-op. A null trigger means it's uninitialized, and setting it to zero-percent
// means we're trying to reset state, so there's nothing to reset in this case.
mCurrPercentage = 0;
return;
}
mCurrPercentage = percent;
mProgressBar.setTriggerPercentage(percent);
}
/**
* Notify the widget that refresh state has changed. Do not call this when
* refresh is triggered by a swipe gesture.
*
* #param refreshing Whether or not the view should show refresh progress.
*/
public void setRefreshing(boolean refreshing) {
if (mRefreshing != refreshing) {
ensureTarget();
mCurrPercentage = 0;
mRefreshing = refreshing;
if (mRefreshing) {
mProgressBar.start();
} else {
mProgressBar.stop();
}
}
}
/**
* Set the four colors used in the progress animation. The first color will
* also be the color of the bar that grows in response to a user swipe
* gesture.
*
* #param colorRes1 Color resource.
* #param colorRes2 Color resource.
* #param colorRes3 Color resource.
* #param colorRes4 Color resource.
*/
public void setColorScheme(int colorRes1, int colorRes2, int colorRes3, int colorRes4) {
ensureTarget();
final Resources res = getResources();
final int color1 = res.getColor(colorRes1);
final int color2 = res.getColor(colorRes2);
final int color3 = res.getColor(colorRes3);
final int color4 = res.getColor(colorRes4);
mProgressBar.setColorScheme(color1, color2, color3,color4);
}
/**
* #return Whether the SwipeRefreshWidget is actively showing refresh
* progress.
*/
public boolean isRefreshing() {
return mRefreshing;
}
private void ensureTarget() {
// Don't bother getting the parent height if the parent hasn't been laid out yet.
if (mTarget == null) {
if (getChildCount() > 1 && !isInEditMode()) {
throw new IllegalStateException(
"SwipeRefreshLayout can host only one direct child");
}
mTarget = getChildAt(0);
mOriginalOffsetTop = mTarget.getTop() + getPaddingTop();
}
if (mDistanceToTriggerSync == -1) {
if (getParent() != null && ((View)getParent()).getHeight() > 0) {
final DisplayMetrics metrics = getResources().getDisplayMetrics();
mDistanceToTriggerSync = (int) Math.min(
((View) getParent()) .getHeight() * MAX_SWIPE_DISTANCE_FACTOR,
REFRESH_TRIGGER_DISTANCE * metrics.density);
}
}
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
mProgressBar.draw(canvas);
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
final int width = getMeasuredWidth();
final int height = getMeasuredHeight();
mProgressBar.setBounds(0, 0, width, mProgressBarHeight);
if (getChildCount() == 0) {
return;
}
final View child = getChildAt(0);
final int childLeft = getPaddingLeft();
final int childTop = mCurrentTargetOffsetTop + getPaddingTop();
final int childWidth = width - getPaddingLeft() - getPaddingRight();
final int childHeight = height - getPaddingTop() - getPaddingBottom();
child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (getChildCount() > 1 && !isInEditMode()) {
throw new IllegalStateException("SwipeRefreshLayout can host only one direct child");
}
if (getChildCount() > 0) {
getChildAt(0).measure(
MeasureSpec.makeMeasureSpec(
getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),
MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(
getMeasuredHeight() - getPaddingTop() - getPaddingBottom(),
MeasureSpec.EXACTLY));
}
}
/**
* #return Whether it is possible for the child view of this layout to
* scroll up. Override this if the child view is a custom view.
*/
public boolean canChildScrollUp() {
if (android.os.Build.VERSION.SDK_INT < 14) {
if (mTarget instanceof AbsListView) {
final AbsListView absListView = (AbsListView) mTarget;
return absListView.getChildCount() > 0
&& (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
.getTop() < absListView.getPaddingTop());
} else {
return mTarget.getScrollY() > 0;
}
} else {
return ViewCompat.canScrollVertically(mTarget, -1);
}
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
ensureTarget();
boolean handled = false;
if (mReturningToStart && ev.getAction() == MotionEvent.ACTION_DOWN) {
mReturningToStart = false;
}
if (isEnabled() && !mReturningToStart && !canChildScrollUp()) {
handled = onTouchEvent(ev);
}
return !handled ? super.onInterceptTouchEvent(ev) : handled;
}
#Override
public void requestDisallowInterceptTouchEvent(boolean b) {
// Nope.
}
#Override
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getAction();
boolean handled = false;
switch (action) {
case MotionEvent.ACTION_DOWN:
mCurrPercentage = 0;
mDownEvent = MotionEvent.obtain(event);
mPrevY = mDownEvent.getY();
break;
case MotionEvent.ACTION_MOVE:
if (mDownEvent != null && !mReturningToStart) {
final float eventY = event.getY();
float yDiff = eventY - mDownEvent.getY();
if (yDiff > mTouchSlop) {
// User velocity passed min velocity; trigger a refresh
if (yDiff > mDistanceToTriggerSync) {
// User movement passed distance; trigger a refresh
startRefresh();
handled = true;
break;
} else {
// Just track the user's movement
setTriggerPercentage(
mAccelerateInterpolator.getInterpolation(
yDiff / mDistanceToTriggerSync));
float offsetTop = yDiff;
if (mPrevY > eventY) {
offsetTop = yDiff - mTouchSlop;
}
updateContentOffsetTop((int) (offsetTop));
if (mPrevY > eventY && (mTarget.getTop() < mTouchSlop)) {
// If the user puts the view back at the top, we
// don't need to. This shouldn't be considered
// cancelling the gesture as the user can restart from the top.
removeCallbacks(mCancel);
} else {
updatePositionTimeout();
}
mPrevY = event.getY();
handled = true;
}
}
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (mDownEvent != null) {
mDownEvent.recycle();
mDownEvent = null;
}
break;
}
return handled;
}
private void startRefresh() {
removeCallbacks(mCancel);
mReturnToStartPosition.run();
setRefreshing(true);
mListener.onRefresh();
}
private void updateContentOffsetTop(int targetTop) {
final int currentTop = mTarget.getTop();
if (targetTop > mDistanceToTriggerSync) {
targetTop = (int) mDistanceToTriggerSync;
} else if (targetTop < 0) {
targetTop = 0;
}
setTargetOffsetTopAndBottom(targetTop - currentTop);
}
private void setTargetOffsetTopAndBottom(int offset) {
mTarget.offsetTopAndBottom(offset);
mCurrentTargetOffsetTop = mTarget.getTop();
}
private void updatePositionTimeout() {
removeCallbacks(mCancel);
postDelayed(mCancel, RETURN_TO_ORIGINAL_POSITION_TIMEOUT);
}
/**
* Classes that wish to be notified when the swipe gesture correctly
* triggers a refresh should implement this interface.
*/
public interface OnRefreshListener {
public void onRefresh();
}
/**
* Simple AnimationListener to avoid having to implement unneeded methods in
* AnimationListeners.
*/
private class BaseAnimationListener implements AnimationListener {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
}
}
I am currently following this answer. As from this answer, it shows that the pixel/grid will be checked if it has been touched. However, I would like to check a grid as a start point and have controls/button at the mainactivity to move the start point around. For example, if user clicks on move forward button, the start point will move forward, checking the new grid and setting the previous point as white. Now i am getting nullpointerexception upon the checkedCell[column][row] in the moveForward() method
So, here is my code:
public class PixelGridView extends View {
private int numColumns, numRows;
private int cellWidth, cellHeight;
private Paint blackPaint = new Paint();
private boolean[][] cellChecked;
public PixelGridView(Context context)
{
this(context, null);
}
public PixelGridView(Context context, AttributeSet attrs)
{
super(context, attrs);
blackPaint.setStyle(Paint.Style.FILL_AND_STROKE);
}
public void setNumColumns(int numColumns)
{
this.numColumns = numColumns;
calculateDimensions();
}
public int getNumColumns()
{
return numColumns;
}
public void setNumRows(int numRows)
{
this.numRows = numRows;
calculateDimensions();
}
public int getNumRows()
{
return numRows;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
calculateDimensions();
}
private void calculateDimensions()
{
if (numColumns == 0 || numRows == 0)
return;
cellWidth = getWidth() / numColumns;
cellHeight = getHeight() / numRows;
cellChecked = new boolean[numColumns][numRows];
invalidate();
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);
if (numColumns == 0 || numRows == 0)
return;
int width = getWidth();
int height = getHeight();
for (int i = 0; i < numColumns; i++)
{
for (int j = 0; j < numRows; j++)
{
if (cellChecked[i][j])
{
canvas.drawRect(i * cellWidth, j * cellHeight, (i + 1) * cellWidth, (j + 1) * cellHeight, blackPaint);
}
}
}
for (int i = 1; i < numColumns; i++)
{
canvas.drawLine(i * cellWidth, 0, i * cellWidth, height, blackPaint);
}
for (int i = 1; i < numRows; i++)
{
canvas.drawLine(0, i * cellHeight, width, i * cellHeight, blackPaint);
}
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
if (event.getAction() != MotionEvent.ACTION_DOWN)
return true;
int column = (int)(event.getX() / cellWidth);
int row = (int)(event.getY() / cellHeight);
cellChecked[column][row] = !cellChecked[column][row];
invalidate();
return true;
}
public void moveForward() {
//set column and row to be checked at [1][1] upon button click on mainactivity
int column = 1;
int row = 1;
cellChecked[column][row] = !cellChecked[column][row];
invalidate();
}
}
and here is my activity to call the moveForward() method
public class MainActivity extends Activity {
PixelGridView pgv;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pgv = new PixelGridView(this);
pgv.setNumColumns(20);
pgv.setNumRows(15);
}
public void onBtnForwardPressed(View view) {
pgv.moveForward();
}
}
and here's the log:
05-10 00:36:33.388: E/AndroidRuntime(8414): Caused by: java.lang.NullPointerException
05-10 00:36:33.388: E/AndroidRuntime(8414): at com.test.PixelGridView.moveForward(PixelGridView.java:131)
05-10 00:36:33.388: E/AndroidRuntime(8414): at com.test.MainActivity.onBtnForwardPressed(MainActivity.java:281)
moveForward() method to move robot:
if (currentAngle == 0) {
for (int i = 0; i < numColumns; i++) {
for (int j = 0; j < numRows; j++) {
if (cellChecked[i][j]) {
column1 = i;
row1 = j;
}
}
}
cellChecked[column1][row1] = !cellChecked[column1][row1];
cellChecked[column1+1][row1] = !cellChecked[column1+1][row1];
invalidate();
}
The PixelGridView object you're creating with new isn't in the Activity's layout, as you've not added it. If you've defined a PixelGridView in the activity_main layout, then you should assign it to pgv using the findViewById() method. If you meant to create it programmatically, then you should add it to the Activity's layout using the addContentView() method.
I have used this tutorial https://code.google.com/p/range-seek-bar/#Example_usage_as_Integer_range?.
Encountered runtime error of my activity stopped. Would like to seek help from you. I attempted to correct the following compile errors as listed below.
RangeSeekBar<Integer> seekBar = new RangeSeekBar<Integer>(20, 75, context);
Context cannot be resolved to a variable
I tried adding changing context to this.
Log.i(TAG, "User selected new range values: MIN=" + minValue + ", MAX=" + maxValue);
TAG cannot be resolved to a variable.
I tried adding "protected static final String TAG = null;" to main activity.
ViewGroup layout = (ViewGroup) findViewById(<your-layout-id>)
Does the layout id refer to my main_activity.xml in my layout?
Really grateful for your feedback.
MainActivity.Java
package com.example.rangeseekbargooglecode;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.ViewGroup;
import com.example.rangeseekbargooglecode.RangeSeekBar.OnRangeSeekBarChangeListener;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final String TAG = null;
// create RangeSeekBar as Integer range between 20 and 75
RangeSeekBar<Integer> seekBar = new RangeSeekBar<Integer>(20, 75, this);
seekBar.setOnRangeSeekBarChangeListener(new OnRangeSeekBarChangeListener<Integer>() {
#Override
public void onRangeSeekBarValuesChanged(RangeSeekBar<?> bar, Integer minValue, Integer maxValue) {
// handle changed range values
Log.i(TAG, "User selected new range values: MIN=" + minValue + ", MAX=" + maxValue);
}
});
// add RangeSeekBar to pre-defined layout
ViewGroup layout = (ViewGroup) findViewById(R.layout.activity_main);
layout.addView(seekBar);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<SeekBar
android:id="#+id/seekBar1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginTop="109dp" />
</RelativeLayout>
Edited Code to allow TextView to display range.
public class MainActivity extends Activity {
private TextView textview;
protected static final String TAG = "com.example.gto_doubleseekbar";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textview = (TextView) findViewById(R.id.textView1);
// create RangeSeekBar as Integer range between 20 and 75
RangeSeekBar<Integer> seekBar = new RangeSeekBar<Integer>(20, 75, this);
seekBar.setOnRangeSeekBarChangeListener(new OnRangeSeekBarChangeListener<Integer>() {
#Override
public void onRangeSeekBarValuesChanged(RangeSeekBar<?> bar, Integer minValue, Integer maxValue) {
// handle changed range values
String powerranger = "User selected new range values: MIN=" + minValue + ", MAX=" + maxValue;
Log.i(TAG, powerranger);
textview.setText(powerranger);
}
});
// add RangeSeekBar to pre-defined layout
LayoutInflater inflater = (LayoutInflater)getApplicationContext().getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.activity_main,null);
layout.addView(seekBar);
setContentView(layout);
}
RangeSeekBar seekBar = new RangeSeekBar(20, 75, context); 1. Context cannot be resolved to a variable
this must work:
RangeSeekBar seekBar = new RangeSeekBar(20, 75, this);
Log.i(TAG, "User selected new range values: MIN=" + minValue + ", MAX=" + maxValue); 2. TAG cannot be resolved to a variable. I tried adding "protected static final String TAG = null;" to main activity.
Don't set it to null. Usually you use the app or component name, e.g.
protected static final String TAG = "MyApp";
ViewGroup layout = (ViewGroup) findViewById() 3. Does the layout id refer to my main_activity.xml in my layout?
Use this:
LayoutInflater inflater = (LayoutInflater)getApplicationContext().getSystemService (Context.LAYOUT_INFLATER_SERVICE);
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.activity_main,null);
layout.addView(seekBar);
setContentView(layout);
Try to implement custom RangeSeekBar.
xml file:
<com.doondoz.utility.common_function.RangeSeekBar
android:id="#+id/seekBarPrice"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:left_index="0"
android:layout_weight="0.90" />
java file:
RangeSeekBar.java
public class RangeSeekBar extends View {
private static final int DEFAULT_HEIGHT = 70;
private static final int DEFAULT_WIDTH = 300;
private static final int DEFAULT_TICK_COUNT = 100;
private Thumb leftThumb, rightThumb;
private Thumb pressedThumb = null;
private SeekBar seekBar;
private Paint thumbPaint;
private OnRangeSeekBarChangerListener mListener;
private int mTickCount;
private int mLeftIndex = 0;
private int mRightIndex;
private int mThumbColor;
private int mThumbNormalRadius;
private int mThumbPressedRadius;
public RangeSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
public RangeSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public RangeSeekBar(Context context) {
super(context);
}
#SuppressWarnings("deprecation")
private void init(Context context, AttributeSet attrs) {
Resources resources = getResources();
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RangeSeekBar);
try {
mTickCount = typedArray.getInteger(R.styleable.RangeSeekBar_tick_count, DEFAULT_TICK_COUNT);
mRightIndex = mTickCount - 1;
mThumbColor = typedArray.getColor(R.styleable.RangeSeekBar_thumb_color, getResources().getColor(R.color.thumb_default));
mThumbNormalRadius = typedArray.getDimensionPixelSize(R.styleable.RangeSeekBar_thumb_normal_radius, 12);
mThumbPressedRadius = typedArray.getDimensionPixelSize(R.styleable.RangeSeekBar_thumb_pressed_radius, 16);
mLeftIndex = typedArray.getInteger(R.styleable.RangeSeekBar_left_index, 0);
mRightIndex = typedArray.getInteger(R.styleable.RangeSeekBar_right_index, mRightIndex);
if (mLeftIndex < 0)
throw new IllegalArgumentException("Left index must be >= 0");
if (mRightIndex > mTickCount)
throw new IllegalArgumentException("Right index must be <= tick count");
} finally {
typedArray.recycle();
}
setUp();
}
private void setUp() {
thumbPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
thumbPaint.setStyle(Paint.Style.FILL);
thumbPaint.setColor(mThumbColor);
leftThumb = new Thumb(0, 0, thumbPaint, mThumbNormalRadius, mThumbPressedRadius);
rightThumb = new Thumb(0, 0, thumbPaint, mThumbNormalRadius, mThumbPressedRadius);
seekBar = new SeekBar(0, 0, 0, Color.BLACK, 1, mThumbColor, 3);
seekBar.setTickNumb(mTickCount);
}
public void setOnRangeBarChangeListener(OnRangeSeekBarChangerListener onRangeBarChangeListener) {
mListener = onRangeBarChangeListener;
}
/**
* Set number of ticks
*
* #param tickCount Default is 100
*/
public void setTickCount(int tickCount) {
mTickCount = tickCount;
seekBar.setTickNumb(mTickCount);
invalidate();
}
/**
* Set thumb's color
*
* #param thumbColor Default is orange
*/
public void setThumbColor(int thumbColor) {
mThumbColor = thumbColor;
thumbPaint.setColor(mThumbColor);
invalidate();
}
/**
* Set thumb's normal radius
*
* #param thumbRadius Default is 6dp
*/
public void setThumbNormalRadius(float thumbRadius) {
mThumbNormalRadius = (int) (thumbRadius*getResources().getDisplayMetrics().density);
leftThumb.radius = mThumbNormalRadius;
rightThumb.radius = mThumbNormalRadius;
invalidate();
}
/**
* Set thumb's pressed radius
*
* #param thumbPressedRadius Default is 8dp
*/
public void setThumbPressedRadius(float thumbPressedRadius) {
mThumbPressedRadius = (int) (thumbPressedRadius*getResources().getDisplayMetrics().density);
leftThumb.pressedRadius = mThumbPressedRadius;
rightThumb.pressedRadius = mThumbPressedRadius;
invalidate();
}
/**
* Set index for the Left Thumb
*
* #param leftIndex Default is 0
*/
public void setLeftIndex(int leftIndex) {
if (leftIndex < 0) {
throw new IllegalArgumentException("Left index must be >= 0");
}
mLeftIndex = leftIndex;
leftThumb.setIndex(seekBar, mLeftIndex);
invalidate();
}
/**
* Set index for the Right thumb
*
* #param rightIndex Default is 99
*/
public void setRightIndex(int rightIndex) {
if (rightIndex > mTickCount) {
throw new IllegalArgumentException("Left index must be <= tick count");
}
mRightIndex = rightIndex;
leftThumb.setIndex(seekBar, mRightIndex);
invalidate();
}
/**
* Get left index
*
* #return int
*/
public int getLeftIndex() {
return mLeftIndex;
}
/**
* Get right index
*
* #return int
*/
public int getRightIndex() {
return mRightIndex;
}
/**
* Get number of tick
*
* #return int
*/
public int getTickCount() {
return mTickCount;
}
#Override
protected synchronized void onDraw(Canvas canvas) {
seekBar.draw(canvas, leftThumb, rightThumb);
leftThumb.draw(canvas);
rightThumb.draw(canvas);
if (pressedThumb != null && pressedThumb.isAnimating) {
invalidate();
}
}
#Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height, width;
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
height = Math.min(heightSize, DEFAULT_HEIGHT);
} else {
height = DEFAULT_HEIGHT;
}
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
width = Math.min(widthSize, DEFAULT_WIDTH);
} else {
width = DEFAULT_WIDTH;
}
setMeasuredDimension(width, height);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
pressedThumb = checkThumbPressed(eventX, eventY);
if (pressedThumb == null) {
return super.onTouchEvent(event);
}
pressedThumb.setPressed(true);
invalidate();
setPressed(true);
return true;
case MotionEvent.ACTION_MOVE:
onActionMove(eventX);
return true;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
if (pressedThumb == null) {
return super.onTouchEvent(event);
}
onActionUp();
break;
}
return super.onTouchEvent(event);
}
private void onActionUp() {
pressedThumb.onActionUp(seekBar);
invalidate();
}
private void onActionMove(float eventX) {
if (eventX >= seekBar.leftX && eventX <= seekBar.rightX) {
pressedThumb.x = eventX;
invalidate();
if (leftThumb.x > rightThumb.x) {
final Thumb temp = leftThumb;
leftThumb = rightThumb;
rightThumb = temp;
}
int leftIndex = seekBar.getNearestTick(leftThumb);
int rightIndex = seekBar.getNearestTick(rightThumb);
if (mLeftIndex != leftIndex || mRightIndex != rightIndex) {
mLeftIndex = leftIndex;
mRightIndex = rightIndex;
if (mListener != null) {
mListener.onIndexChange(this, mLeftIndex, mRightIndex);
}
}
}
}
private Thumb checkThumbPressed(float eventX, float eventY) {
Thumb result = null;
boolean isLeftThumbPressed = leftThumb.isInTargetZone(eventX, eventY);
boolean isRightThumbPressed = rightThumb.isInTargetZone(eventX, eventY);
if (isLeftThumbPressed && isRightThumbPressed) {
result = (eventX / getWidth() >= 0.5f) ? leftThumb : rightThumb;
} else if (isLeftThumbPressed) {
result = leftThumb;
} else if (isRightThumbPressed) {
result = rightThumb;
}
return result;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
leftThumb.x = (getPaddingLeft() + 20 + leftThumb.normalRadius / 2);
leftThumb.y = (h + getPaddingTop() + getPaddingBottom()) / 2;
rightThumb.y = leftThumb.y;
rightThumb.x = (w - getPaddingRight() - 20 - rightThumb.normalRadius / 2);
seekBar.leftX = leftThumb.x;
seekBar.rightX = rightThumb.x;
seekBar.y = leftThumb.y;
leftThumb.setIndex(seekBar, mLeftIndex);
rightThumb.setIndex(seekBar, mRightIndex);
}
#Override
protected Parcelable onSaveInstanceState() {
Bundle bundle = new Bundle();
SavedState state = new SavedState(super.onSaveInstanceState());
state.tickCount = mTickCount;
state.leftIndex = mLeftIndex;
state.rightIndex = mRightIndex;
state.thumbColor = mThumbColor;
state.thumbNormalRadius = mThumbNormalRadius;
state.thumbPressedRadius = mThumbPressedRadius;
bundle.putParcelable(SavedState.STATE,state);
return bundle;
}
#Override
protected void onRestoreInstanceState(Parcelable state) {
if (state instanceof Bundle) {
Bundle bundle = (Bundle) state;
SavedState savedState = bundle.getParcelable(SavedState.STATE);
mTickCount = savedState.tickCount;
mThumbColor = savedState.thumbColor;
mThumbNormalRadius = savedState.thumbNormalRadius;
mThumbPressedRadius = savedState.thumbPressedRadius;
mLeftIndex = savedState.leftIndex;
mRightIndex = savedState.rightIndex;
super.onRestoreInstanceState(savedState.getSuperState());
return;
}
super.onRestoreInstanceState(SavedState.EMPTY_STATE);
}
public interface OnRangeSeekBarChangerListener {
void onIndexChange(RangeSeekBar rangeBar, int leftIndex, int rightIndex);
}
static class SavedState extends BaseSavedState {
static final String STATE = "RangeSeekBar.STATE";
int tickCount;
int leftIndex;
int rightIndex;
int thumbColor;
int thumbNormalRadius;
int thumbPressedRadius;
SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
}
#Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
}
public static final Creator<SavedState> CREATOR =
new Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
this is my code which i follow from code.google.com this link http://code.google.com/p/android-playground/source/browse/#svn%2Ftrunk%2FSwipeyTabsSample
just tell me how do i add activites in this application? is show same activity in all tabs
public class SwipeyTabsSampleActivity extends FragmentActivity {
private static final String [] TITLES = {
"CATEGORIES",
"FEATURED",
"TOP PAID",
"TOP FREE",
"TOP GROSSING",
"TOP NEW PAID",
"TOP NEW FREE",
"TRENDING",
};
private SwipeyTabs mTabs;
private ViewPager mViewPager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_swipeytab);
mViewPager = (ViewPager) findViewById(R.id.viewpager);
mTabs = (SwipeyTabs) findViewById(R.id.swipeytabs);
SwipeyTabsPagerAdapter adapter = new SwipeyTabsPagerAdapter(this,
getSupportFragmentManager());
mViewPager.setAdapter(adapter);
mTabs.setAdapter(adapter);
mViewPager.setOnPageChangeListener(mTabs);
mViewPager.setCurrentItem(0);
}
private class SwipeyTabsPagerAdapter extends FragmentPagerAdapter implements
SwipeyTabsAdapter {
private final Context mContext;
public SwipeyTabsPagerAdapter(Context context, FragmentManager fm) {
super(fm);
this.mContext = context;
}
#Override
public Fragment getItem(int position) {
return SwipeyTabFragment.newInstance(TITLES[position]);
}
#Override
public int getCount() {
return TITLES.length;
}
public TextView getTab(final int position, SwipeyTabs root) {
TextView view = (TextView) LayoutInflater.from(mContext).inflate(
R.layout.swipey_tab_indicator, root, false);
view.setText(TITLES[position]);
view.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mViewPager.setCurrentItem(position);
}
});
return view;
}
}
}
public interface SwipeyTabsAdapter {
/**
* Return the number swipey tabs. Needs to be aligned with the number of
* items in your {#link PagerAdapter}.
*
* #return
*/
int getCount();
/**
* Build {#link TextView} to diplay as a swipey tab.
*
* #param position the position of the tab
* #param root the root view
* #return
*/
TextView getTab(int position, SwipeyTabs root);
}
public class SwipeyTabs extends ViewGroup implements
OnPageChangeListener {
protected final String TAG = "SwipeyTabs";
private SwipeyTabsAdapter mAdapter;
private int mCurrentPos = -1;
// height of the bar at the bottom of the tabs
private int mBottomBarHeight = 2;
// height of the indicator for the fronted tab
private int mTabIndicatorHeight = 3;
// color for the bottom bar, fronted tab
private int mBottomBarColor = 0xff96aa39;
// text color for all other tabs
private int mTextColor = 0xff949494;
// holds the positions of the fronted tabs
private int[] mFrontedTabPos;
// holds the positions of the target position when swiping left
private int[] mLeftTabPos;
// holds the positions of the target position when swiping right
private int[] mRightTabPos;
// holds the positions of the current position on screen
private int[] mCurrentTabPos;
private Paint mCachedTabPaint;
private int mWidth = -1;
public SwipeyTabs(Context context) {
this(context, null);
}
public SwipeyTabs(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SwipeyTabs(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
final TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.SwipeyTabs, defStyle, 0);
mBottomBarColor = a.getColor(R.styleable.SwipeyTabs_bottomBarColor,
mBottomBarColor);
mBottomBarHeight = a.getDimensionPixelSize(
R.styleable.SwipeyTabs_bottomBarHeight, 2);
mTabIndicatorHeight = a.getDimensionPixelSize(
R.styleable.SwipeyTabs_tabIndicatorHeight, 3);
a.recycle();
init();
}
/**
* Initialize the SwipeyTabs {#link ViewGroup}
*/
private void init() {
// enable the horizontal fading edges which will be drawn by the parent
// View
setHorizontalFadingEdgeEnabled(true);
setFadingEdgeLength((int) (getResources().getDisplayMetrics().density *
35.0f + 0.5f));
setWillNotDraw(false);
mCachedTabPaint = new Paint();
mCachedTabPaint.setColor(mBottomBarColor);
}
/**
* Set the adapter.
*
* #param adapter
*/
public void setAdapter(SwipeyTabsAdapter adapter) {
if (mAdapter != null) {
// TODO: data set observer
}
mAdapter = adapter;
mCurrentPos = -1;
mFrontedTabPos = null;
mLeftTabPos = null;
mRightTabPos = null;
mCurrentTabPos = null;
// clean up our childs
removeAllViews();
if (mAdapter != null) {
final int count = mAdapter.getCount();
// add the child text views
for (int i = 0; i < count; i++) {
addView(mAdapter.getTab(i, this));
}
mCurrentPos = 0;
mFrontedTabPos = new int[count];
mLeftTabPos = new int[count];
mRightTabPos = new int[count];
mCurrentTabPos = new int[count];
mWidth = -1;
requestLayout();
}
}
/**
* Calculate the fronted, left and right positions
*
* #param forceLayout
* force the current positions to the values of the calculated
* fronted positions
*/
private void updateTabPositions(boolean forceLayout) {
if (mAdapter == null) {
return;
}
calculateTabPosition(mCurrentPos, mFrontedTabPos);
calculateTabPosition(mCurrentPos + 1, mLeftTabPos);
calculateTabPosition(mCurrentPos - 1, mRightTabPos);
updateEllipsize();
if (forceLayout) {
final int count = mAdapter.getCount();
for (int i = 0; i < count; i++) {
mCurrentTabPos[i] = mFrontedTabPos[i];
}
}
}
/**
* Calculate the position of the tabs.
*
* #param position
* the position of the fronted tab
* #param tabPositions
* the array in which to store the result
*/
private void calculateTabPosition(int position, int[] tabPositions) {
if (mAdapter == null) {
return;
}
final int count = mAdapter.getCount();
if (position >= 0 && position < count) {
final int width = getMeasuredWidth();
final View centerTab = getChildAt(position);
tabPositions[position] = width / 2 - centerTab.getMeasuredWidth()
/ 2;
for (int i = position - 1; i >= 0; i--) {
final TextView tab = (TextView) getChildAt(i);
if (i == position - 1) {
tabPositions[i] = 0 - tab.getPaddingLeft();
} else {
tabPositions[i] = 0 - tab.getMeasuredWidth() -
width;
}
tabPositions[i] = Math.min(tabPositions[i], tabPositions[i
+ 1]
- tab.getMeasuredWidth());
}
for (int i = position + 1; i < count; i++) {
final TextView tab = (TextView) getChildAt(i);
if (i == position + 1) {
tabPositions[i] = width - tab.getMeasuredWidth()
+ tab.getPaddingRight();
} else {
tabPositions[i] = width * 2;
}
final TextView prevTab = (TextView) getChildAt(i - 1);
tabPositions[i] = Math.max(tabPositions[i], tabPositions[i
- 1]
+ prevTab.getMeasuredWidth());
}
} else {
for (int i = 0; i < tabPositions.length; i++) {
tabPositions[i] = -1;
}
}
}
/**
* Update the ellipsize of the text views
*/
private void updateEllipsize() {
if (mAdapter == null) {
return;
}
final int count = mAdapter.getCount();
for (int i = 0; i < count; i++) {
TextView tab = (TextView) getChildAt(i);
if (i < mCurrentPos) {
tab.setEllipsize(null);
tab.setGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL);
} else if (i == mCurrentPos) {
tab.setEllipsize(TruncateAt.END);
tab.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
} else if (i > mCurrentPos) {
tab.setEllipsize(null);
tab.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
}
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
measureTabs(widthMeasureSpec, heightMeasureSpec);
int height = 0;
final View v = getChildAt(0);
if (v != null) {
height = v.getMeasuredHeight();
}
setMeasuredDimension(
resolveSize(getPaddingLeft() + widthSize +
getPaddingRight(),
widthMeasureSpec),
resolveSize(height + mBottomBarHeight + getPaddingTop()
+ getPaddingBottom(), heightMeasureSpec));
if (mWidth != widthSize) {
mWidth = widthSize;
updateTabPositions(true);
}
}
/**
* Measure our tab text views
*
* #param widthMeasureSpec
* #param heightMeasureSpec
*/
private void measureTabs(int widthMeasureSpec, int heightMeasureSpec) {
if (mAdapter == null) {
return;
}
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
final int maxWidth = (int) (widthSize * 0.6);
final int count = mAdapter.getCount();
for (int i = 0; i < count; i++) {
LayoutParams layoutParams = (LayoutParams) getChildAt(i)
.getLayoutParams();
final int widthSpec = MeasureSpec.makeMeasureSpec(maxWidth,
MeasureSpec.AT_MOST);
final int heightSpec = MeasureSpec.makeMeasureSpec(
layoutParams.height, MeasureSpec.EXACTLY);
getChildAt(i).measure(widthSpec, heightSpec);
}
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (mAdapter == null) {
return;
}
final int count = mAdapter.getCount();
for (int i = 0; i < count; i++) {
View v = getChildAt(i);
v.layout(mCurrentTabPos[i], this.getPaddingTop(), mCurrentTabPos[i]
+ v.getMeasuredWidth(),
this.getPaddingTop() + v.getMeasuredHeight());
}
}
#Override
protected void dispatchDraw(Canvas canvas) {
if (mCurrentPos != -1) {
// calculate the relative position of the fronted tab to set the
// alpha channel of the tab indicator
final int tabSelectedTop = getHeight() - getPaddingBottom()
- mBottomBarHeight - mTabIndicatorHeight;
final View currentTab = getChildAt(mCurrentPos);
final int centerOfTab = (mCurrentTabPos[mCurrentPos] + currentTab
.getMeasuredWidth()) -
(currentTab.getMeasuredWidth() / 2);
final int center = getWidth() / 2;
final int centerDiv3 = center / 3;
final float relativePos = 1.0f - Math.min(
Math.abs((float) (centerOfTab - center)
/ (float) (centerDiv3)), 1.0f);
mCachedTabPaint.setAlpha((int) (255 * relativePos));
canvas.drawRect(
mCurrentTabPos[mCurrentPos],
tabSelectedTop,
mCurrentTabPos[mCurrentPos] +
currentTab.getMeasuredWidth(),
tabSelectedTop + mTabIndicatorHeight,
mCachedTabPaint);
// set the correct text colors on the text views
final int count = mAdapter.getCount();
for (int i = 0; i < count; i++) {
final TextView tab = (TextView) getChildAt(i);
if (mCurrentPos == i) {
tab.setTextColor(interpolateColor(mBottomBarColor,
mTextColor, 1.0f - relativePos));
} else {
tab.setTextColor(mTextColor);
}
}
}
super.dispatchDraw(canvas);
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
// draw the bottom bar
final int bottomBarTop = getHeight() - getPaddingBottom()
- mBottomBarHeight;
mCachedTabPaint.setAlpha(0xff);
canvas.drawRect(0, bottomBarTop, getWidth(), bottomBarTop
+ mBottomBarHeight, mCachedTabPaint);
}
#Override
protected float getLeftFadingEdgeStrength() {
// forced so that we will always have the left fading edge
return 1.0f;
}
#Override
protected float getRightFadingEdgeStrength() {
// forced so that we will always have the right fading edge
return 1.0f;
}
public void onPageScrollStateChanged(int state) {
}
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
if (mAdapter == null) {
return;
}
final int count = mAdapter.getCount();
float x = 0.0f;
int dir = 0;
// detect the swipe direction
if (positionOffsetPixels != 0 && mCurrentPos == position) {
dir = -1;
x = positionOffset;
} else if (positionOffsetPixels != 0 && mCurrentPos != position) {
dir = 1;
x = 1.0f - positionOffset;
}
// update the current positions
for (int i = 0; i < count; i++) {
final float curX = mFrontedTabPos[i];
float toX = 0.0f;
if (dir < 0) {
toX = mLeftTabPos[i];
} else if (dir > 0) {
toX = mRightTabPos[i];
} else {
toX = mFrontedTabPos[i];
}
final int offsetX = (int) ((toX - curX) * x + 0.5f);
final int newX = (int) (curX + offsetX);
mCurrentTabPos[i] = newX;
}
requestLayout();
invalidate();
}
public void onPageSelected(int position) {
mCurrentPos = position;
updateTabPositions(false);
}
private int interpolateColor(final int color1, final int color2,
float fraction) {
final float alpha1 = Color.alpha(color1) / 255.0f;
final float red1 = Color.red(color1) / 255.0f;
final float green1 = Color.green(color1) / 255.0f;
final float blue1 = Color.blue(color1) / 255.0f;
final float alpha2 = Color.alpha(color2) / 255.0f;
final float red2 = Color.red(color2) / 255.0f;
final float green2 = Color.green(color2) / 255.0f;
final float blue2 = Color.blue(color2) / 255.0f;
final float deltaAlpha = alpha2 - alpha1;
final float deltaRed = red2 - red1;
final float deltaGreen = green2 - green1;
final float deltaBlue = blue2 - blue1;
float alpha = alpha1 + (deltaAlpha * fraction);
float red = red1 + (deltaRed * fraction);
float green = green1 + (deltaGreen * fraction);
float blue = blue1 + (deltaBlue * fraction);
alpha = Math.max(Math.min(alpha, 1f), 0f);
red = Math.max(Math.min(red, 1f), 0f);
green = Math.max(Math.min(green, 1f), 0f);
blue = Math.max(Math.min(blue, 1f), 0f);
return Color.argb((int) (alpha * 255.0f), (int) (red * 255.0f),
(int) (green * 255.0f), (int) (blue * 255.0f));
}
}
public class SwipeyTabFragment extends Fragment {
public static Fragment newInstance(String title) {
SwipeyTabFragment f = new SwipeyTabFragment();
Bundle args = new Bundle();
args.putString("title", title);
f.setArguments(args);
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_swipeytab,
null);
final String title = getArguments().getString("title");
((TextView) root.findViewById(R.id.text)).setText(title);
return root;
}
}
just tell me how do i add activites in this application? is show same activity in all tabs
You don't. Having activities-in-tabs was deprecated well over two years ago.
A ViewPager typically uses fragments for its pages, as is demonstrated in the code you pasted above. In this sample, each page is a SwipeyTabFragment, but you are welcome to have pages be different fragment classes if you prefer. You are also welcome to not use fragments and use custom Views instead for the pages. But there is no support for putting activities as pages.
I have a list of events which are seperated by month and year (Jun 2010, Jul 2010 etc.). I have enabled fast scrolling because the list is really long. I've also implemented SectionIndexer so that people can see what month and year they are currently viewing when scrolling down the list of events at speed.
I don't have any problem with the implementation, just how the information is shown. Fast scrolling with SectionIndexer seems to only really be able to support a label with a single letter. If the list was alphabetised this would be perfect, however I want it to display a bit more text.
If you look at the screenshot bellow you'll see the problem I'm having.
(source: matto1990.com)
What I want to know is: is it possible to change how the text in the centre of the screen is displayed. Can I change it somehow to make it look right (with the background covering all of the text).
Thanks in advance. If you need any clarification, or code just ask.
EDIT: Full sample code for this solution available here.
I had this same problem - I needed to display full text in the overlay rectangle rather than just a single character. I managed to solve it using the following code as an example: http://code.google.com/p/apps-for-android/source/browse/trunk/RingsExtended/src/com/example/android/rings_extended/FastScrollView.java
The author said that this was copied from the Contacts app, which apparently uses its own implementation rather than just setting fastScrollEnabled="true" on the ListView. I altered it a little bit so that you can customize the overlay rectangle width, overlay rectangle height, overlay text size, and scroll thumb width.
For the record, the final result looks like this: http://nolanwlawson.files.wordpress.com/2011/03/pokedroid_1.png
All you need to do is add these values to your res/values/attrs.xml:
<declare-styleable name="CustomFastScrollView">
<attr name="overlayWidth" format="dimension"/>
<attr name="overlayHeight" format="dimension"/>
<attr name="overlayTextSize" format="dimension"/>
<attr name="overlayScrollThumbWidth" format="dimension"/>
</declare-styleable>
And then use this CustomFastScrollView instead of the one in the link:
public class CustomFastScrollView extends FrameLayout
implements OnScrollListener, OnHierarchyChangeListener {
private Drawable mCurrentThumb;
private Drawable mOverlayDrawable;
private int mThumbH;
private int mThumbW;
private int mThumbY;
private RectF mOverlayPos;
// custom values I defined
private int mOverlayWidth;
private int mOverlayHeight;
private float mOverlayTextSize;
private int mOverlayScrollThumbWidth;
private boolean mDragging;
private ListView mList;
private boolean mScrollCompleted;
private boolean mThumbVisible;
private int mVisibleItem;
private Paint mPaint;
private int mListOffset;
private Object [] mSections;
private String mSectionText;
private boolean mDrawOverlay;
private ScrollFade mScrollFade;
private Handler mHandler = new Handler();
private BaseAdapter mListAdapter;
private boolean mChangedBounds;
public static interface SectionIndexer {
Object[] getSections();
int getPositionForSection(int section);
int getSectionForPosition(int position);
}
public CustomFastScrollView(Context context) {
super(context);
init(context, null);
}
public CustomFastScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public CustomFastScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
private void useThumbDrawable(Drawable drawable) {
mCurrentThumb = drawable;
mThumbW = mOverlayScrollThumbWidth;//mCurrentThumb.getIntrinsicWidth();
mThumbH = mCurrentThumb.getIntrinsicHeight();
mChangedBounds = true;
}
private void init(Context context, AttributeSet attrs) {
// set all attributes from xml
if (attrs != null) {
TypedArray typedArray = context.obtainStyledAttributes(attrs,
R.styleable.CustomFastScrollView);
mOverlayHeight = typedArray.getDimensionPixelSize(
R.styleable.CustomFastScrollView_overlayHeight, 0);
mOverlayWidth = typedArray.getDimensionPixelSize(
R.styleable.CustomFastScrollView_overlayWidth, 0);
mOverlayTextSize = typedArray.getDimensionPixelSize(
R.styleable.CustomFastScrollView_overlayTextSize, 0);
mOverlayScrollThumbWidth = typedArray.getDimensionPixelSize(
R.styleable.CustomFastScrollView_overlayScrollThumbWidth, 0);
}
// Get both the scrollbar states drawables
final Resources res = context.getResources();
Drawable thumbDrawable = res.getDrawable(R.drawable.scrollbar_handle_accelerated_anim2);
useThumbDrawable(thumbDrawable);
mOverlayDrawable = res.getDrawable(android.R.drawable.alert_dark_frame);
mScrollCompleted = true;
setWillNotDraw(false);
// Need to know when the ListView is added
setOnHierarchyChangeListener(this);
mOverlayPos = new RectF();
mScrollFade = new ScrollFade();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setTextSize(mOverlayTextSize);
mPaint.setColor(0xFFFFFFFF);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
}
private void removeThumb() {
mThumbVisible = false;
// Draw one last time to remove thumb
invalidate();
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
if (!mThumbVisible) {
// No need to draw the rest
return;
}
final int y = mThumbY;
final int viewWidth = getWidth();
final CustomFastScrollView.ScrollFade scrollFade = mScrollFade;
int alpha = -1;
if (scrollFade.mStarted) {
alpha = scrollFade.getAlpha();
if (alpha < ScrollFade.ALPHA_MAX / 2) {
mCurrentThumb.setAlpha(alpha * 2);
}
int left = viewWidth - (mThumbW * alpha) / ScrollFade.ALPHA_MAX;
mCurrentThumb.setBounds(left, 0, viewWidth, mThumbH);
mChangedBounds = true;
}
canvas.translate(0, y);
mCurrentThumb.draw(canvas);
canvas.translate(0, -y);
// If user is dragging the scroll bar, draw the alphabet overlay
if (mDragging && mDrawOverlay) {
mOverlayDrawable.draw(canvas);
final Paint paint = mPaint;
float descent = paint.descent();
final RectF rectF = mOverlayPos;
canvas.drawText(mSectionText, (int) (rectF.left + rectF.right) / 2,
(int) (rectF.bottom + rectF.top) / 2 + descent, paint);
} else if (alpha == 0) {
scrollFade.mStarted = false;
removeThumb();
} else {
invalidate(viewWidth - mThumbW, y, viewWidth, y + mThumbH);
}
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (mCurrentThumb != null) {
mCurrentThumb.setBounds(w - mThumbW, 0, w, mThumbH);
}
final RectF pos = mOverlayPos;
pos.left = (w - mOverlayWidth) / 2;
pos.right = pos.left + mOverlayWidth;
pos.top = h / 10; // 10% from top
pos.bottom = pos.top + mOverlayHeight;
mOverlayDrawable.setBounds((int) pos.left, (int) pos.top,
(int) pos.right, (int) pos.bottom);
}
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
if (totalItemCount - visibleItemCount > 0 && !mDragging) {
mThumbY = ((getHeight() - mThumbH) * firstVisibleItem) / (totalItemCount - visibleItemCount);
if (mChangedBounds) {
final int viewWidth = getWidth();
mCurrentThumb.setBounds(viewWidth - mThumbW, 0, viewWidth, mThumbH);
mChangedBounds = false;
}
}
mScrollCompleted = true;
if (firstVisibleItem == mVisibleItem) {
return;
}
mVisibleItem = firstVisibleItem;
if (!mThumbVisible || mScrollFade.mStarted) {
mThumbVisible = true;
mCurrentThumb.setAlpha(ScrollFade.ALPHA_MAX);
}
mHandler.removeCallbacks(mScrollFade);
mScrollFade.mStarted = false;
if (!mDragging) {
mHandler.postDelayed(mScrollFade, 1500);
}
}
private void getSections() {
Adapter adapter = mList.getAdapter();
if (adapter instanceof HeaderViewListAdapter) {
mListOffset = ((HeaderViewListAdapter)adapter).getHeadersCount();
adapter = ((HeaderViewListAdapter)adapter).getWrappedAdapter();
}
if (adapter instanceof SectionIndexer) {
mListAdapter = (BaseAdapter) adapter;
mSections = ((SectionIndexer) mListAdapter).getSections();
}
}
public void onChildViewAdded(View parent, View child) {
if (child instanceof ListView) {
mList = (ListView)child;
mList.setOnScrollListener(this);
getSections();
}
}
public void onChildViewRemoved(View parent, View child) {
if (child == mList) {
mList = null;
mListAdapter = null;
mSections = null;
}
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (mThumbVisible && ev.getAction() == MotionEvent.ACTION_DOWN) {
if (ev.getX() > getWidth() - mThumbW && ev.getY() >= mThumbY &&
ev.getY() <= mThumbY + mThumbH) {
mDragging = true;
return true;
}
}
return false;
}
private void scrollTo(float position) {
int count = mList.getCount();
mScrollCompleted = false;
final Object[] sections = mSections;
int sectionIndex;
if (sections != null && sections.length > 1) {
final int nSections = sections.length;
int section = (int) (position * nSections);
if (section >= nSections) {
section = nSections - 1;
}
sectionIndex = section;
final SectionIndexer baseAdapter = (SectionIndexer) mListAdapter;
int index = baseAdapter.getPositionForSection(section);
// Given the expected section and index, the following code will
// try to account for missing sections (no names starting with..)
// It will compute the scroll space of surrounding empty sections
// and interpolate the currently visible letter's range across the
// available space, so that there is always some list movement while
// the user moves the thumb.
int nextIndex = count;
int prevIndex = index;
int prevSection = section;
int nextSection = section + 1;
// Assume the next section is unique
if (section < nSections - 1) {
nextIndex = baseAdapter.getPositionForSection(section + 1);
}
// Find the previous index if we're slicing the previous section
if (nextIndex == index) {
// Non-existent letter
while (section > 0) {
section--;
prevIndex = baseAdapter.getPositionForSection(section);
if (prevIndex != index) {
prevSection = section;
sectionIndex = section;
break;
}
}
}
// Find the next index, in case the assumed next index is not
// unique. For instance, if there is no P, then request for P's
// position actually returns Q's. So we need to look ahead to make
// sure that there is really a Q at Q's position. If not, move
// further down...
int nextNextSection = nextSection + 1;
while (nextNextSection < nSections &&
baseAdapter.getPositionForSection(nextNextSection) == nextIndex) {
nextNextSection++;
nextSection++;
}
// Compute the beginning and ending scroll range percentage of the
// currently visible letter. This could be equal to or greater than
// (1 / nSections).
float fPrev = (float) prevSection / nSections;
float fNext = (float) nextSection / nSections;
index = prevIndex + (int) ((nextIndex - prevIndex) * (position - fPrev)
/ (fNext - fPrev));
// Don't overflow
if (index > count - 1) index = count - 1;
mList.setSelectionFromTop(index + mListOffset, 0);
} else {
int index = (int) (position * count);
mList.setSelectionFromTop(index + mListOffset, 0);
sectionIndex = -1;
}
if (sectionIndex >= 0) {
String text = mSectionText = sections[sectionIndex].toString();
mDrawOverlay = (text.length() != 1 || text.charAt(0) != ' ') &&
sectionIndex < sections.length;
} else {
mDrawOverlay = false;
}
}
private void cancelFling() {
// Cancel the list fling
MotionEvent cancelFling = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0);
mList.onTouchEvent(cancelFling);
cancelFling.recycle();
}
#Override
public boolean onTouchEvent(MotionEvent me) {
if (me.getAction() == MotionEvent.ACTION_DOWN) {
if (me.getX() > getWidth() - mThumbW
&& me.getY() >= mThumbY
&& me.getY() <= mThumbY + mThumbH) {
mDragging = true;
if (mListAdapter == null && mList != null) {
getSections();
}
cancelFling();
return true;
}
} else if (me.getAction() == MotionEvent.ACTION_UP) {
if (mDragging) {
mDragging = false;
final Handler handler = mHandler;
handler.removeCallbacks(mScrollFade);
handler.postDelayed(mScrollFade, 1000);
return true;
}
} else if (me.getAction() == MotionEvent.ACTION_MOVE) {
if (mDragging) {
final int viewHeight = getHeight();
mThumbY = (int) me.getY() - mThumbH + 10;
if (mThumbY < 0) {
mThumbY = 0;
} else if (mThumbY + mThumbH > viewHeight) {
mThumbY = viewHeight - mThumbH;
}
// If the previous scrollTo is still pending
if (mScrollCompleted) {
scrollTo((float) mThumbY / (viewHeight - mThumbH));
}
return true;
}
}
return super.onTouchEvent(me);
}
public class ScrollFade implements Runnable {
long mStartTime;
long mFadeDuration;
boolean mStarted;
static final int ALPHA_MAX = 200;
static final long FADE_DURATION = 200;
void startFade() {
mFadeDuration = FADE_DURATION;
mStartTime = SystemClock.uptimeMillis();
mStarted = true;
}
int getAlpha() {
if (!mStarted) {
return ALPHA_MAX;
}
int alpha;
long now = SystemClock.uptimeMillis();
if (now > mStartTime + mFadeDuration) {
alpha = 0;
} else {
alpha = (int) (ALPHA_MAX - ((now - mStartTime) * ALPHA_MAX) / mFadeDuration);
}
return alpha;
}
public void run() {
if (!mStarted) {
startFade();
invalidate();
}
if (getAlpha() > 0) {
final int y = mThumbY;
final int viewWidth = getWidth();
invalidate(viewWidth - mThumbW, y, viewWidth, y + mThumbH);
} else {
mStarted = false;
removeThumb();
}
}
}
}
You can also tweak the translucency of the scroll thumb using ALPHA_MAX.
Then put something like this in your layout xml file:
<com.myapp.CustomFastScrollView android:layout_width="wrap_content"
android:layout_height="fill_parent"
myapp:overlayWidth="175dp" myapp:overlayHeight="110dp" myapp:overlayTextSize="36dp"
myapp:overlayScrollThumbWidth="60dp" android:id="#+id/fast_scroll_view">
<ListView android:id="#android:id/list" android:layout_width="wrap_content"
android:layout_height="fill_parent"/>
<TextView android:id="#android:id/empty"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="" />
</com.myapp.CustomFastScrollView>
Don't forget to declare your attributes in that layout xml file as well:
... xmlns:myapp= "http://schemas.android.com/apk/res/com.myapp" ...
You'll also need to grab the R.drawable.scrollbar_handle_accelerated_anim2 drawables from that Android source code. The link above only contains the mdpi one.
The FastScroller widget is responsible for drawing the overlay. You should probably take a look at its source:
https://android.googlesource.com/platform/frameworks/base/+/gingerbread-release/core/java/android/widget/FastScroller.java
Search for comment:
// If user is dragging the scroll bar, draw the alphabet overlay