I am trying to make TextView which moves across the screen in all directions randomly using translateAnimation. I need text moving like in screen saver for example going round and round until it is clicked.But have some problems:
1. text moves just from top to bottom
2.it doesn't stop in screen borders , it is going off the screen then coming back again :
public class aktivityStarted extends AppCompatActivity {
TextView textMovin;
/* int loc[]=new int[2];
int x=loc[0];
int y=loc[1];*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_aktivity_started);
textMovin=findViewById(R.id.movingText);
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
final int width = displaymetrics.widthPixels-textMovin.getWidth();
final int height = displaymetrics.heightPixels-textMovin.getHeight();
final Random r = new Random();
final int translationX = r.nextInt(width);
final int translationY = r.nextInt(height);
final int randomx=r.nextInt(50)+1;
final int randomy=r.nextInt(50)+1;
final TranslateAnimation anim = new TranslateAnimation(-translationX,translationX ,-translationY,translationY ); //Use current view position instead of `currentX` and `currentY`
anim.setDuration(2500);
anim.setRepeatCount(-1);
anim.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
anim.reset();
anim.setRepeatMode(Animation.REVERSE);
anim.setFillAfter(true);
}
#Override
public void onAnimationRepeat(Animation animation) {
textMovin.setY(r.nextInt(height));
textMovin.setX(r.nextInt(width));
anim.start();
}
});
textMovin.startAnimation(anim);
}
}
try this code:
public class MainActivity extends AppCompatActivity {
private View parent;
private TextView textMovin;
private float speedX;
private float speedY;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textMovin = findViewById(R.id.textV);
parent = findViewById(R.id.parent);
final Random r = new Random();
speedX = r.nextFloat() * 200;
speedY = r.nextFloat() * 200;
parent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
final int width = parent.getWidth() - textMovin.getWidth();
final int height = parent.getHeight() - textMovin.getHeight();
final int period = 50;
new Timer().scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
textMovin.post(new TimerTask() {
#Override
public void run() {
textMovin.setX(speedX * period / 1000.0f + textMovin.getX());
textMovin.setY(speedY * period / 1000.0f + textMovin.getY());
if (textMovin.getY() <= 0 || textMovin.getY() >= height)
speedY *= -1;
if (textMovin.getX() <= 0 || textMovin.getX() >= width)
speedX *= -1;
}
});
}
}, 50, period);
}
});
findViewById(R.id.random).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Random r = new Random();
speedX = r.nextFloat() * 200;
speedY = r.nextFloat() * 200;
}
});
}
}
and the layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="#+id/textV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Hello World!" />
<Button
android:id="#+id/random"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="10dp"
android:text="Random" />
</RelativeLayout>
Hope it works for you.
public class OnDragTouchListener implements View.OnTouchListener {
/**
* Callback used to indicate when the drag is finished
*/
public interface OnDragActionListener {
/**
* Called when drag event is started
*
* #param view The view dragged
*/
void onDragStart(View view);
/**
* Called when drag event is completed
*
* #param view The view dragged
*/
void onDragEnd(View view);
}
private View mView;
private View mParent;
private boolean isDragging;
private boolean isInitialized = false;
private int width;
private float xWhenAttached;
private float maxLeft;
private float maxRight;
private float dX;
private int height;
private float yWhenAttached;
private float maxTop;
private float maxBottom;
private float dY;
private OnDragActionListener mOnDragActionListener;
public OnDragTouchListener(View view) {
this(view, (View) view.getParent(), null);
}
public OnDragTouchListener(View view, View parent) {
this(view, parent, null);
}
public OnDragTouchListener(View view, OnDragActionListener onDragActionListener) {
this(view, (View) view.getParent(), onDragActionListener);
}
public OnDragTouchListener(View view, View parent, OnDragActionListener onDragActionListener) {
initListener(view, parent);
setOnDragActionListener(onDragActionListener);
}
public void setOnDragActionListener(OnDragActionListener onDragActionListener) {
mOnDragActionListener = onDragActionListener;
}
public void initListener(View view, View parent) {
mView = view;
mParent = parent;
isDragging = false;
isInitialized = false;
}
public void updateBounds() {
updateViewBounds();
updateParentBounds();
isInitialized = true;
}
public void updateViewBounds() {
width = mView.getWidth();
xWhenAttached = mView.getX();
dX = 0;
height = mView.getHeight();
yWhenAttached = mView.getY();
dY = 0;
}
public void updateParentBounds() {
maxLeft = 0;
maxRight = maxLeft + mParent.getWidth();
maxTop = 0;
maxBottom = maxTop + mParent.getHeight();
}
#Override
public boolean onTouch(View v, MotionEvent event) {
if (isDragging) {
float[] bounds = new float[4];
// LEFT
bounds[0] = event.getRawX() + dX;
if (bounds[0] < maxLeft) {
bounds[0] = maxLeft;
}
// RIGHT
bounds[2] = bounds[0] + width;
if (bounds[2] > maxRight) {
bounds[2] = maxRight;
bounds[0] = bounds[2] - width;
}
// TOP
bounds[1] = event.getRawY() + dY;
if (bounds[1] < maxTop) {
bounds[1] = maxTop;
}
// BOTTOM
bounds[3] = bounds[1] + height;
if (bounds[3] > maxBottom) {
bounds[3] = maxBottom;
bounds[1] = bounds[3] - height;
}
switch (event.getAction()) {
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
onDragFinish();
break;
case MotionEvent.ACTION_MOVE:
mView.animate().x(bounds[0]).y(bounds[1]).setDuration(0).start();
break;
}
return true;
} else {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isDragging = true;
if (!isInitialized) {
updateBounds();
}
dX = v.getX() - event.getRawX();
dY = v.getY() - event.getRawY();
if (mOnDragActionListener != null) {
mOnDragActionListener.onDragStart(mView);
}
return true;
}
}
return false;
}
private void onDragFinish() {
if (mOnDragActionListener != null) {
mOnDragActionListener.onDragEnd(mView);
}
dX = 0;
dY = 0;
isDragging = false;
}
}
And you can set it using:
myView.setOnTouchListener(new OnDragTouchListener(myView));
Or by adding this directly in init method of your Custom View:
setOnTouchListener(new OnDragTouchListener(this));
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 making an android app that uses a SwipeRefreshLayout around a RelativeLayout in a fragment in a ViewPager. When I first open the app and swipe to refresh, the refresh disc shows, but it is blank with no colors.
http://i.stack.imgur.com/VzUeB.png
Then, the next time I swipe to refresh, there is no preview of the refresh (the disc does not come down), and when I release, it takes a second to show. I think it only runs when swipeRefreshLayout.setRefreshing(false) is called, and so it only shows for a split second.
This is my code:
swipeRefreshLayout = (SwipeRefreshLayout)view.findViewById(R.id.swipe_container);
swipeRefreshLayout.setColorSchemeResources(R.color.accentColor, R.color.colorPrimary, R.color.colorPrimaryDark);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
TypedValue typed_value = new TypedValue();
getActivity().getTheme().resolveAttribute(android.support.v7.appcompat.R.attr.actionBarSize, typed_value, true);
DisplayMetrics dm = getResources().getDisplayMetrics();
int height = dm.heightPixels;
swipeRefreshLayout.setProgressViewOffset(false, -200, height / 8);
swipeRefreshLayout.post(new Runnable() {
#Override
public void run() {
swipeRefreshLayout.setRefreshing(true);
}
});
try {
result = new GetReadResultTask().execute().get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
if (result != null && connected) {
AlphaAnimation fadeOut = new AlphaAnimation(1.0f, 0.0f);
AlphaAnimation fadeIn = new AlphaAnimation(0.0f, 1.0f);
stepsTextView.setAnimation(fadeOut);
fadeOut.setDuration(1200);
fadeOut.setFillAfter(true);
List<Bucket> buckets = result.getBuckets();
for (int iii = 0; iii < buckets.size(); iii++) {
dumpDataSet(buckets.get(iii).getDataSet(DataType.AGGREGATE_STEP_COUNT_DELTA));
}
stepsTextView.setAnimation(fadeIn);
fadeIn.setDuration(1200);
fadeIn.setFillAfter(true);
series.resetData(data);
}
swipeRefreshLayout.post(new Runnable() {
#Override
public void run() {
swipeRefreshLayout.setRefreshing(false);
}
});
}
});
Use following code for this..
SwipeActivity Activity is as follows..
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);
}
}
SwipeRefreshLayout is follows.
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) {
}
}
}
following is manifest file..
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.swiperefreshlayout"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.swiperefreshlayout.SwipeActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Just copy paste all code in your project and you will get your desired output.
I am developing one app where I am dragging around my ImageView in Activity.
I have configured Facebook Rebound library for spring animation which is originally used in Facebook Messenger's chat heads animations. I want to add this kind of animations to my ImageView when I drag it.
VIDEO
So far I am able to get spring animation when I touch ImageView (implemented spring on rootview), this is my code. How can I implement that natural type of dragging effect to my ImageView.
public class MainTry extends Activity {
int windowwidth;
int windowheight;
private LayoutParams layoutParams;
private final BaseSpringSystem mSpringSystem = SpringSystem.create();
private FrameLayout mRootView;
private Spring spring;
private View mImageView;
private VelocityTracker velocity = null;
private float dx;
private float dy;
private View rootView;
private ImageView img;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout);
// Create a system to run the physics loop for a set of springs.
SpringSystem springSystem = SpringSystem.create();
// Add a spring to the system.
spring = springSystem.createSpring();
rootView = getWindow().getDecorView()
.findViewById(android.R.id.content);
windowwidth = getWindowManager().getDefaultDisplay().getWidth();
windowheight = getWindowManager().getDefaultDisplay().getHeight();
img = (ImageView) findViewById(R.id.imageView2);
rootView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// spring.setEndValue(1);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
// spring.setEndValue(0);
break;
}
return true;
}
});
// Add a listener to observe the motion of the spring.
spring.addListener(new SimpleSpringListener() {
#Override
public void onSpringUpdate(Spring spring) {
// You can observe the updates in the spring
// state by asking its current value in onSpringUpdate.
float value = (float) spring.getCurrentValue();
float scale = .5f - (value * 0.1f);
img.setScaleX(scale);
img.setScaleY(scale);
}
});
// spring.setEndValue(1);
img.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
LayoutParams layoutParams = (LayoutParams) img
.getLayoutParams();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
dx = event.getRawX() - 10;
dy = event.getRawY() - 10;
if (velocity == null) {
// Retrieve a new VelocityTracker object to watch the
// velocity of a motion.
velocity = VelocityTracker.obtain();
} else {
// Reset the velocity tracker back to its initial state.
velocity.clear();
}
break;
case MotionEvent.ACTION_MOVE:
dx = event.getRawX() - 10;
dy = event.getRawY() - 10;
velocity.addMovement(event);
spring.setVelocity(velocity.getYVelocity());
spring.setCurrentValue(dy);
spring.setEndValue(dy);
layoutParams.leftMargin = (int) dx - 10;
layoutParams.topMargin = (int) dy - 10;
img.setLayoutParams(layoutParams);
break;
case MotionEvent.ACTION_CANCEL:
break;
case MotionEvent.ACTION_UP:
velocity.addMovement(event);
spring.setVelocity(velocity.getYVelocity());
spring.setCurrentValue(event.getRawY() - 10);
spring.setEndValue(0);
break;
default:
break;
}
return true;
}
});
}
#Override
public void onResume() {
super.onResume();
}
#Override
public void onPause() {
super.onPause();
}
}
what about this:
class V extends View implements SpringListener {
private static final int NUM_ELEMS = 4;
private Spring[] mXSprings = new Spring[NUM_ELEMS];
private Spring[] mYSprings = new Spring[NUM_ELEMS];
private Paint mPaint = new Paint();
private Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
public V(Context context) {
super(context);
SpringSystem ss = SpringSystem.create();
Spring s;
for (int i = 0; i < NUM_ELEMS; i++) {
s = ss.createSpring();
s.setSpringConfig(new MySpringConfig(200, i == 0? 8 : 15 + i * 2, i, true));
s.addListener(this);
mXSprings[i] = s;
s = ss.createSpring();
s.setSpringConfig(new MySpringConfig(200, i == 0? 8 : 15 + i * 2, i, false));
s.addListener(this);
mYSprings[i] = s;
}
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mXSprings[0].setCurrentValue(w / 2);
mYSprings[0].setCurrentValue(0);
mXSprings[0].setEndValue(w / 2);
mYSprings[0].setEndValue(h / 2);
}
#Override
public void onSpringActivate(Spring s) {
}
#Override
public void onSpringAtRest(Spring s) {
}
#Override
public void onSpringEndStateChange(Spring s) {
}
#Override
public void onSpringUpdate(Spring s) {
MySpringConfig cfg = (MySpringConfig) s.getSpringConfig();
if (cfg.index < NUM_ELEMS - 1) {
Spring[] springs = cfg.horizontal? mXSprings : mYSprings;
springs[cfg.index + 1].setEndValue(s.getCurrentValue());
}
if (cfg.index == 0) {
invalidate();
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
mXSprings[0].setEndValue(event.getX());
mYSprings[0].setEndValue(event.getY());
return true;
}
#Override
protected void onDraw(Canvas canvas) {
for (int i = NUM_ELEMS - 1; i >= 0; i--) {
mPaint.setAlpha(i == 0? 255 : 192 - i * 128 / NUM_ELEMS);
canvas.drawBitmap(mBitmap,
(float) mXSprings[i].getCurrentValue() - mBitmap.getWidth() / 2,
(float) mYSprings[i].getCurrentValue() - mBitmap.getHeight() / 2,
mPaint);
}
}
class MySpringConfig extends SpringConfig {
int index;
boolean horizontal;
public MySpringConfig(double tension, double friction, int index, boolean horizontal) {
super(tension, friction);
this.index = index;
this.horizontal = horizontal;
}
}
}
i have used above V class directly in Window-manager and it's work perfectly and chatHead move like facebook messenger.
public class ChatHeadService extends Service
{
private LayoutInflater inflater;
private WindowManager windowManager;
private Point szWindow = new Point();
#Override
public void onCreate()
{
super.onCreate();
Log.v(Utils.LogTag, "Start Service");
}
private
void handleStart(){
windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
if (Build . VERSION . SDK_INT >= Build . VERSION_CODES . HONEYCOMB) {
windowManager . getDefaultDisplay() . getSize(szWindow);
} else {
int w = windowManager . getDefaultDisplay() . getWidth();
int h = windowManager . getDefaultDisplay() . getHeight();
szWindow . set(w, h);
}
WindowManager . LayoutParams params = new WindowManager . LayoutParams(
WindowManager . LayoutParams . WRAP_CONTENT,
WindowManager . LayoutParams . WRAP_CONTENT,
WindowManager . LayoutParams . TYPE_PHONE,
WindowManager . LayoutParams . FLAG_NOT_FOCUSABLE |
WindowManager . LayoutParams . FLAG_WATCH_OUTSIDE_TOUCH |
WindowManager . LayoutParams . FLAG_LAYOUT_NO_LIMITS,
PixelFormat . TRANSLUCENT
);
params . gravity = Gravity . TOP | Gravity . LEFT;
params . x = 50;
params . y = 100;
V vImg = new V(this);
windowManager . addView(vImg, params);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
if (startId == Service . START_STICKY) {
handleStart();
}
}
return super . onStartCommand(intent, flags, startId);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy(){
super . onDestroy();
if (windowManager != null) {
// windowManager.removeView(chatHeadView);
}
}
}
I am creating a floor map with n number of dynamic buttons with incremental value and added to a custom relative layout. Now i need to create onclicklistner for each buttons added to a view. How to get the id or some unique value to identify which button is clicked. Can somebody please help me on this i am breaking my head for the past 10 days. Thanks in advance.
This is my Custom Relative layout :
public class InteractiveView extends RelativeLayout implements OnClickListener{
Matrix matrix = new Matrix();
private float mPositionX = 0;
private float mPositionY = 0;
private float mScale = 0.1f;
private Context context;
private boolean canvasFlag = true;
public InteractiveView(Context context) {
super(context);
this.context = context;
this.setWillNotDraw(false);
// this.setOnTouchListener(mTouchListener);
this.setOnClickListener(this);
}
public void setPosition(float lPositionX, float lPositionY){
mPositionX = lPositionX;
mPositionY = lPositionY;
}
public void setMovingPosition(float lPositionX, float lPositionY){
mPositionX += lPositionX;
mPositionY += lPositionY;
}
public void setScale(float lScale){
mScale = lScale;
}
protected void dispatchDraw(Canvas canvas) {
canvas.save();
// canvas.setMatrix(matrix);
Log.e("Canvas Height ",canvas.getWidth()+" "+canvas.getHeight());
Log.e("Canvas Height ",getWidth() /14 +" "+getHeight()/12 );
Log.e("Canvas Density "," "+canvas.getDensity() );
canvas.translate(mPositionX*mScale, mPositionY*mScale);
canvas.translate(getWidth() / 14,getHeight() / 12);
if (mScale < 0.10)
mScale = 0.1f;
canvas.scale(mScale, mScale);
Log.e("Scale : ",mScale+" ");
super.dispatchDraw(canvas);
canvas.restore();
}
// touch events
private final int NONE = 0;
private final int DRAG = 1;
private final int ZOOM = 2;
private final int CLICK = 3;
// pinch to zoom
private float mOldDist;
private float mNewDist;
private float mScaleFactor = 0.01f;
// position
private float mPreviousX;
private float mPreviousY;
int mode = NONE;
#SuppressWarnings("deprecation")
public OnTouchListener mTouchListener = new OnTouchListener(){
public boolean onTouch(View v, MotionEvent e) {
/*Button button = (Button)v;
Log.e("Button Text : "," "+button.getText().toString());
*/
float x = e.getX();
float y = e.getY();
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN: // one touch: drag
mode = CLICK;
break;
case MotionEvent.ACTION_POINTER_2_DOWN: // two touches: zoom
mOldDist = spacing(e);
mode = ZOOM; // zoom
break;
case MotionEvent.ACTION_UP: // no mode
mode = NONE;
break;
case MotionEvent.ACTION_POINTER_2_UP: // no mode
mode = NONE;
break;
case MotionEvent.ACTION_MOVE: // rotation
if (e.getPointerCount() > 1 && mode == ZOOM) {
/*mNewDist = spacing(e) - mOldDist;
mScale += mNewDist*mScaleFactor;
invalidate();
mOldDist = spacing(e); */
} else if (mode == CLICK || mode == DRAG) {
float dx = (x - mPreviousX)/mScale;
float dy = (y - mPreviousY)/mScale;
setMovingPosition(dx, dy);
invalidate();
mode = DRAG;
}
break;
}
mPreviousX = x;
mPreviousY = y;
return true;
}
};
// finds spacing
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y)/4;
}
This is my fragment class where i create floor map :
public class FloorMapFragment extends Fragment implements OnClickListener {
ViewGroup root;
Button exhibitor;
ZoomControls zoom;
int id = 0;
float dx=0,dy=0,x=0,y=0;
InteractiveView mInteractiveView;
int startX, startY;
boolean isClicked = false;
int unit = 100;
int incremental = 100;
int new_X;
int i;
int new_Width = new_X + incremental;
int new_Y;
int new_Hight = new_Y + incremental;
int leftMargin, topMargin;
int orange = Color.parseColor("#C0680F");
int maroon = Color.parseColor("#5F0C0C");
int pink = Color.parseColor("#F45C91");
int moov = Color.parseColor("#6E4689");
int gray = Color.parseColor("#777777");
int red = Color.parseColor("#E31E26");
int blue = Color.parseColor("#3A53A4");
int green = Color.parseColor("#70BD59");
int cyan = Color.parseColor("#70CDDD");
RelativeLayout r;
// View mainView = null;
// Remember some things for zooming
PointF start = new PointF();
PointF mid = new PointF();
float oldDist = 1f;
PointF oldDistPoint = new PointF();
public static String TAG = "ZOOM";
int mScreenWidth = 0;
int mScreenHeight= 0;
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
enum Direction {
LEFT, RIGHT, UP, DOWN
};
FloorListner listner;
#SuppressWarnings("deprecation")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
root = (ViewGroup) inflater.inflate(R.layout.floor_main, null);
// mainView = (RelativeLayout)root.findViewById(R.id.zoom_layout);
r = (RelativeLayout) root.findViewById(R.id.my_relative_layout);
zoom = (ZoomControls)root. findViewById(R.id.zoomControls1);
mScreenWidth = r.getWidth();
/*MainActivity.activity.getResources()
.getDisplayMetrics().widthPixels;*/
mScreenHeight = r.getHeight();
/*MainActivity.activity.getResources()
.getDisplayMetrics().heightPixels; */
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT,
RelativeLayout.LayoutParams.FILL_PARENT);
layoutParams.height = 75;
layoutParams.width = 57;
// layoutParams.bottomMargin = 100;
// layoutParams.setMargins(0, 0, 0, 100);
// layoutParams.setMargins(-220, 0, 0, 0);
/*ImageView lImageView = new ImageView(MainActivity.activity);
lImageView.setLayoutParams(new RelativeLayout.LayoutParams(-1,-1));
lImageView.setImageResource(R.drawable.transparentimage);;*/
mInteractiveView = new InteractiveView(MainActivity.activity);
// mInteractiveView.setOnClickListener(this);
// mInteractiveView.setOnTouchListener(mTouchListener);
// mInteractiveView.setLayoutParams(new RelativeLayout.LayoutParams(-5,-5 ));
// mInteractiveView.setLayoutParams(layoutParams);
// mInteractiveView.setPosition(-mScreenWidth/2, -mScreenHeight/2);
zoom.setOnZoomInClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
float x = r.getScaleX();
float y = r.getScaleY();
Log.e("Zoon In Listener : ", "X Scale : "+ x );
Log.e("Zoon In Listener : ", "Y Scale : "+ y );
Log.e("Zoon In Width : ", "X Scale : "+ r.getWidth() );
Log.e("Zoon In Height : ", "Y Scale : "+ r.getHeight() );
if (x <= 6.0 && y <= 6.0){
r.setScaleX((float) (x + 0.5));
r.setScaleY((float) (y + 0.5));
}
}
});
zoom.setOnZoomOutClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
float x = r.getScaleX();
float y = r.getScaleY();
Log.e("Zoon Out Listener : ", "X Scale : "+ x );
Log.e("Zoon Out Listener : ", "Y Scale : "+ y );
if (x > 1.0 && y > 1.0){
r.setScaleX((float) (x - 0.5));
r.setScaleY((float) (y - 0.5));
}
}
});
ProgressDialog d = new ProgressDialog(getActivity());
d.setMessage("Loading Map");
d.show();
draw();
d.dismiss();
/*
mInteractiveView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
});*/
/*for( i=0; i<((ViewGroup)mInteractiveView).getChildCount(); ++i) {
View nextChild = ((ViewGroup)mInteractiveView).getChildAt(i);
try {
final Button b = (Button) nextChild;
Log.e("Button Text : ", " : "+b.getText().toString());
b.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
int index = ((ViewGroup)b.getParent()).indexOfChild(b);
Log.e("Button get Id : ", ""+v.getTag().toString());
}
});
} catch (Exception e) {
}
}*/
//
// mInteractiveView.addView(lImageView);
// r.setLayoutParams(layoutParams);
r.addView(mInteractiveView);
/* ExhibitorDAO dao = new ExhibitorDAO(getActivity());
workAround(dao, "K19");*/
/* Fragment fragment = new NewsFragment();
FragmentTransaction trans = ;
trans.addToBackStack(null);
trans.replace(R.id.main, fragment);
trans.commit();*/
// r.setOnTouchListener(MyOnTouchListener);
// r.setLayoutParams(layoutParams);
Log.e("Width And Height : ", "Width : "+r.getLayoutParams().width+ " : Height :"+r.getLayoutParams().height);
return root;
}
private OnTouchListener mTouchListener = new OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
isClicked = true;
x = event.getX();
y = event.getY();
dx = x-r.getX();
dy = y-r.getY();
break;
case MotionEvent.ACTION_UP:
if (isClicked){
isClicked = false;
/*Button b = (Button) v;
ExhibitorDAO dao = new ExhibitorDAO(getActivity());
workAround(dao,b.getText().toString());*/
}
break;
case MotionEvent.ACTION_POINTER_UP:
isClicked = false;
break;
case MotionEvent.ACTION_POINTER_DOWN:
isClicked = false;
break;
case MotionEvent.ACTION_MOVE:
r.setX(event.getX()-dx);
r.setY(event.getY()-dy);
isClicked = false;
break;
default:
break;
}
return false;
}
};
private void decreaseXBy(int i) {
new_X = new_X - (2 * i);
}
private void reset() {
new_X = 0;
new_Y += incremental;
;
}
private void drawingH(Direction direction, float width) {
if (direction == direction.RIGHT) {// means go to right direction{
new_X += (incremental * width);
} else if (direction == direction.LEFT) { // means go to left
new_X -= (incremental * width);
}
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Button b = (Button) v;
ExhibitorDAO dao = new ExhibitorDAO(getActivity());
try{
Exhibitor exhibitor = new Exhibitor();
Log.e("Button Text : ", " : "+b.getText());
if (!b.getText().equals("")) {
Logger.log("floor:");
exhibitor = dao.getExhibitorByBooth(b.getText().toString());
ExhibitorApplication ex = new ExhibitorApplication();
ex.exhibitor = exhibitor;
if (exhibitor != null){
listner.Onfloorclick();
ex.fav_exhibitor = 4 ;
Logger.log("floor:"+ex.exhibitor.Exhibitor_FileNumber);
}
else
{
Logger.log("floor:"+ex.exhibitor.Exhibitor_FileNumber);
}
}
{
Logger.log("floor:no data");
}
}
catch(Exception ex)
{
Toast.makeText(getActivity(), "No Information "+ex.getMessage(), Toast.LENGTH_SHORT).show();
}
}
public Button drawExhibitor(float width, int height, int color,
String label, String fileNumber, Direction d) {
exhibitor = new Button(getActivity());
// exhibitor.setOnClickListener(this);
// exhibitor.setOnTouchListener(MyOnTouchListener);
if (color == Color.BLUE)
exhibitor.setBackgroundColor(Color.parseColor("#56A5EC"));
if (color == Color.WHITE)
exhibitor.setAlpha(0);
else
exhibitor.setBackgroundColor(color);
// exhibitor.setId(id);
// id++;
exhibitor.setText(label);
exhibitor.setTextSize(8);
// exhibitor.setId(foo);
exhibitor.setTag(label);
exhibitor.setTypeface(Typeface.DEFAULT_BOLD);
exhibitor.setGravity(Gravity.CENTER);
exhibitor.setTextColor(Color.WHITE);
/*exhibitor.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.e("Button get Id : ", ""+exhibitor.getId());
}
});*/
exhibitor.setOnTouchListener(mTouchListener);
leftMargin = new_X;
topMargin = new_Y;
drawingH(d, width);
InteractiveView.LayoutParams params = new InteractiveView.LayoutParams(
(int) (width * incremental), height * incremental);
params.leftMargin = leftMargin;
params.topMargin = topMargin;
mInteractiveView.addView(exhibitor, params);
params = null;
if (color != Color.WHITE) {
drawingHSpace();
}
return exhibitor;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof FloorListner) {
listner = (FloorListner) activity;
} else {
throw new ClassCastException(activity.toString()
+ " must implemenet MyListFragment.OnItemSelectedListener");
}
}
private void drawingHSpace() {
new_X += 2;
}
private void drawingHSpace(float t) {
new_X = (int) (new_X + (2 * t));
}
private void drawingVSpace() {
new_Y += 2;
}
private void removeDrawingVSpace() {
new_Y -= 2;
}
private void decreaseXBy(float i) {
new_X = (int) (new_X - (2 * i));
}
private void drawLabel(float width, int height, int color, int drawable, Direction d) {
// TODO Auto-generated method stub
TextView image = new TextView(getActivity());
//image.setText(label);
image.setBackgroundResource(drawable);
image.setGravity(Gravity.CENTER);
image.setTextSize(20);
image.setTypeface(Typeface.DEFAULT_BOLD);
//image.setTextColor(color);
// image.setOnTouchListener(MyOnTouchListener);
leftMargin = new_X;
topMargin = new_Y;
drawingH(d,width);
InteractiveView.LayoutParams params = new InteractiveView.LayoutParams(
(int)(width * incremental), height * incremental);
params.leftMargin = leftMargin;
params.topMargin = topMargin;
mInteractiveView.addView(image, params);
}
private void drawLabel(float width, int height, int color, String label, Direction d) {
// TODO Auto-generated method stub
TextView image = new TextView(getActivity());
image.setText(label);
image.setGravity(Gravity.CENTER);
image.setTextSize(20);
image.setTypeface(Typeface.DEFAULT_BOLD);
image.setTextColor(color);
// image.setOnTouchListener(mTouchListener);
leftMargin = new_X;
topMargin = new_Y;
drawingH(d,width);
InteractiveView.LayoutParams params = new InteractiveView.LayoutParams(
(int)(width * incremental), height * incremental);
params.leftMargin = leftMargin;
params.topMargin = topMargin;
mInteractiveView.addView(image, params);
}
private void draw() {
drawExhibitor(28.5F, 3, Color.WHITE, "", "", Direction.RIGHT);
drawLabel(2, 3, blue, R.drawable.al_mamzar, Direction.RIGHT);
reset();
reset();
drawExhibitor(16.5F, 1, Color.WHITE, "", "", Direction.RIGHT);
drawLabel(2, 1, blue, R.drawable.business_center, Direction.RIGHT);
drawExhibitor(4.65F, 1, Color.WHITE, "", "", Direction.RIGHT);
drawLabel(1, 1, blue, R.drawable.bath_f, Direction.RIGHT);
drawExhibitor(14F, 1, Color.WHITE, "", "", Direction.RIGHT);
drawLabel(1, 1, blue, R.drawable.bath_m, Direction.RIGHT);
//reset();
reset();
drawingVSpace();
drawingVSpace();
}
}
Finally i am adding the Interactive View to a relative layout.
As you will find it in the documentation that each view can have an id (using setId (int id) or from xml android:id ) or tag(using setTag (int key)) associated with it and later on you can get that id or tag via getId() or getTag().
Now before you actually retrieve any id for a view at first you have to set an id for that specific view either via programmatically or via xml.
If you don't specify any id for a view and you are trying get that view's id you will get NO_ID.
As per documentation: getId () returns this view's identifier.A positive integer used to identify the view or NO_ID if the view has no ID.
Now to address your problem, before you add a button to your viewgroup assign a unique id to that button.
To illustrate more here is an example:
public class MainActivity extends Activity {
private LinearLayout mRootLayout;
private OnClickListener mOnClickListener = new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Log.e("mButton "," onClick");
Toast.makeText(MainActivity.this, " "+arg0.getId(), Toast.LENGTH_LONG).show();
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRootLayout = (LinearLayout)findViewById(R.id.mRootLayout);
for(int i = 0;i<10;i++){
Button mButton = new Button(this);
mButton.setText("Button "+i);
mButton.setId(i);
if(i<9){
mButton.setOnClickListener(mOnClickListener);
}
mRootLayout.addView(mButton);
}
Button testFindButton = (Button)mRootLayout.findViewById(9);
testFindButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Log.e("testFindButton "," onClick");
Toast.makeText(MainActivity.this, " testFindButton "+v.getId(), Toast.LENGTH_LONG).show();
}
});
}
}
You can use the setTag method for each button, to set an id. Then in the onClick method, retrieve that value, and execute the code related to that button.
Some code (not tested):
private OnClickListener listener = new OnClickListener()
{
#Override
public void onClick(View v)
{
int id = (Integer)v.getTag();
switch (id)
{
case 1: break;
....
}
}
});
for (int i=0 ; i<N ; i++)
{
yourbutton.setTag(Integer.valueOf(i));
yourbutton.setOnClickListener(listener);
}
I want one of my ViewGroup to be movable. Let's say, I want to click on it and the content below it reveals. On second click it closes again. Kind of sliding menu behaviour.
Here are my classes:
Custom scroller:
public class MyScroller implements Runnable {
private static final String TAG = "MY_SCROLLER";
private static final int ANIMATION_DURATION = 500;
private final Scroller mScroller;
private View mScrollingView;
private int lastX = 0;
private static final Interpolator sInterpolator = new Interpolator() {
public float getInterpolation(float t) {
t -= 1.0f;
return t * t * t * t * t + 1.0f;
}
};
MyScroller(final View view) {
mScroller = new android.widget.Scroller(view.getContext(), sInterpolator);
mScrollingView = view;
}
public void start(int initialVelocity) {
Log.d(TAG, "start() called");
int initialX = mScrollingView.getScrollX();
int maxX = mScrollingView.getWidth();
mScroller.startScroll(0, 0, maxX, 0, ANIMATION_DURATION);
lastX = initialX;
mScrollingView.post(this);
}
public void run() {
Log.d(TAG, "run() called");
if (mScroller.isFinished()) {
mScrollingView.invalidate();
return;
}
boolean more = mScroller.computeScrollOffset();
int x = mScroller.getCurrX();
int diff = x - lastX;
if (diff != 0) {
Log.d(TAG, "x = " + x);
mScrollingView.offsetLeftAndRight(diff);
mScrollingView.invalidate();
lastX = x;
} else {
forceFinished();
}
if (more) {
mScrollingView.postDelayed(this, 16);
}
}
void forceFinished() {
if (!mScroller.isFinished()) {
mScroller.forceFinished(true);
mScrollingView.invalidate();
}
}
}
and usage:
viewGroup.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new MyScroller(v).start(0);
}
});
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new MyScroller(v).start(0);
}
});
For Button everything works fine - it smoothly moves.
But ViewGroups that I tried leave a trail like on screenshot.
RelativeLayout with Button inside left a trail.
Standalone Button moved perfectly.
What am I missing here?