ScrollView in SlidingUpPanel Never works - java

I have tried everything to get my ScrollView and SlidingUpPanelLayout to function how Google Maps app handles it. (video example)
This is the only link that seems to actually be working for people, but it is not working for me.
https://stackoverflow.com/a/22720204/172336
I've followed it 4 times today and every time my ScrollView scrolls and my SlidingUpPanelLayout does absolutely nothing. (It sits there)
Here is the code I am adding to the code from the SlidingUpPanelLayout as seen on GitHub.
activity_main.xml
<com.bouy76.sportsmantracker.SlidingUpPanelLayout
android:id="#+id/sliding_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:gravity="bottom"
app:panelHeight="68dp"
app:dragView="#+id/drag_view"
app:scrollView="#+id/scroll_view"> <!-- attrs.xml tag -->
<!-- MAIN CONTENT -->
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="top">
<com.nutiteq.MapView
android:id="#+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
<!-- SLIDING LAYOUT -->
<RelativeLayout
android:id="#+id/drag_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="false"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="68dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center|start"
android:paddingLeft="#dimen/activity_vertical_margin"
android:text="Near Beaver Creek"
android:textSize="20sp" />
</LinearLayout>
<ScrollView
android:id="#+id/scroll_view" <!-- Match attrs reference -->
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#android:color/transparent"
android:cacheColorHint="#android:color/white"
android:divider="#android:color/darker_gray"
android:dividerHeight="#dimen/divider_height"
android:layout_marginTop="68dp"
android:drawSelectorOnTop="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="5000dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:orientation="vertical"/>
</LinearLayout>
</ScrollView>
</RelativeLayout>
</com.bouy76.sportsmantracker.SlidingUpPanelLayout>
SlidingUpPanelLayout.java
View mScrollView;
int mScrollViewResId = -1;
boolean isChildHandlingTouch = false;
float mPrevMotionX;
float mPrevMotionY;
...
#Override
protected void onFinishInflate() {
super.onFinishInflate();
if (mDragViewResId != -1) {
setDragView(findViewById(mDragViewResId));
}
if (mScrollViewResId != -1) {
mScrollView = findViewById(mScrollViewResId);
}
}
...
private boolean isScrollViewUnder(int x, int y) {
if (mScrollView == null)
return false;
int[] viewLocation = new int[2];
mScrollView.getLocationOnScreen(viewLocation);
int[] parentLocation = new int[2];
this.getLocationOnScreen(parentLocation);
int screenX = parentLocation[0] + x;
int screenY = parentLocation[1] + y;
return screenX >= viewLocation[0] &&
screenX < viewLocation[0] + mScrollView.getWidth() &&
screenY >= viewLocation[1] &&
screenY < viewLocation[1] + mScrollView.getHeight();
}
...
//Removed the onInterceptTouchEvent Method
...
public boolean onTouchEvent(MotionEvent ev) {
if (!mCanSlide || !mIsSlidingEnabled) {
return super.onTouchEvent(ev);
}
mDragHelper.processTouchEvent(ev);
final int action = ev.getAction();
boolean wantTouchEvents = false;
switch (action & MotionEventCompat.ACTION_MASK) {
case MotionEvent.ACTION_UP: {
final float x = ev.getX();
final float y = ev.getY();
final float dx = x - mInitialMotionX;
final float dy = y - mInitialMotionY;
final int slop = mDragHelper.getTouchSlop();
View dragView = mDragView != null ? mDragView : mSlideableView;
if (dx * dx + dy * dy < slop * slop &&
isDragViewUnder((int) x, (int) y) &&
!isScrollViewUnder((int) x, (int) y)) {
dragView.playSoundEffect(SoundEffectConstants.CLICK);
if (!isExpanded() && !isAnchored()) {
expandPane(mAnchorPoint);
} else {
collapsePane();
}
break;
}
break;
}
}
return wantTouchEvents;
}
...
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (mScrollView == null)
return super.dispatchTouchEvent(ev);
final int action = MotionEventCompat.getActionMasked(ev);
final float x = ev.getX();
final float y = ev.getY();
if (action == MotionEvent.ACTION_DOWN) {
mDragHelper.shouldInterceptTouchEvent(ev);
mInitialMotionX = mPrevMotionX = x;
mInitialMotionY = mPrevMotionY = y;
isChildHandlingTouch = false;
} else if (action == MotionEvent.ACTION_MOVE) {
float dx = x - mPrevMotionX;
float dy = y - mPrevMotionY;
mPrevMotionX = x;
mPrevMotionY = y;
if (!isScrollViewUnder((int) x, (int) y))
return this.onTouchEvent(ev);
if (dy > 0) { // DOWN
// Is the child less than fully scrolled?
// Then let the child handle it.
if (mScrollView.getScrollY() > 0) {
isChildHandlingTouch = true;
return super.dispatchTouchEvent(ev);
}
if (isChildHandlingTouch) {
// Send an 'UP' event to the child.
MotionEvent up = MotionEvent.obtain(ev);
up.setAction(MotionEvent.ACTION_UP);
super.dispatchTouchEvent(up);
up.recycle();
ev.setAction(MotionEvent.ACTION_DOWN);
}
isChildHandlingTouch = false;
return this.onTouchEvent(ev);
} else if (dy < 0) {
if (mSlideOffset > 0.0f) {
isChildHandlingTouch = false;
return this.onTouchEvent(ev);
}
if (!isChildHandlingTouch) {
mDragHelper.cancel();
ev.setAction(MotionEvent.ACTION_DOWN);
}
isChildHandlingTouch = true;
return super.dispatchTouchEvent(ev);
}
} else if ((action == MotionEvent.ACTION_CANCEL) ||
(action == MotionEvent.ACTION_UP)) {
if (!isChildHandlingTouch) {
final float dx = x - mInitialMotionX;
final float dy = y - mInitialMotionY;
final int slop = mDragHelper.getTouchSlop();
if ((mIsUsingDragViewTouchEvents) &&
(dx * dx + dy * dy < slop * slop))
return super.dispatchTouchEvent(ev);
return this.onTouchEvent(ev);
}
}
return super.dispatchTouchEvent(ev);
}
Again check this for where I'm pulling code.
https://stackoverflow.com/a/22720204/172336
Thanks

Related

How to resize the bitmap image in this flood Fill algorithm code and custom view

I am new to programming and I am trying to implement a flood fill algorithm to colorize selected part in the image as a color book app.
I have found this link which provides full working code (but slow) for the algorithm. and also provide QueueLinearFloodFiller which is way faster.
The problem is that The custom MyView class is added to Relativelayout to show the bitmap that will be colored but the image is out of the view like this
I want to wrap it to fill the view and take its size like in wrap_content
I have tried to use this code to resize it
dashBoard = (RelativeLayout) findViewById(R.id.dashBoard);
int width = RelativeLayout.LayoutParams.WRAP_CONTENT;
int hight = RelativeLayout.LayoutParams.WRAP_CONTENT;
myView.setLayoutParams(new RelativeLayout.LayoutParams(width,hight));
dashBoard.addView(myView);
but it didn't work.
here is the full code and the XML
public class UnicornColorActivity extends AppCompatActivity {
private RelativeLayout dashBoard;
private MyView myView;
public ImageView image;
Button b_red, b_blue, b_green, b_orange, b_clear;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myView = new MyView(this);
setContentView(R.layout.activity_unicorn_color);
findViewById(R.id.dashBoard);
b_red = (Button) findViewById(R.id.b_red);
b_blue = (Button) findViewById(R.id.b_blue);
b_green = (Button) findViewById(R.id.b_green);
b_orange = (Button) findViewById(R.id.b_orange);
b_red.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myView.changePaintColor(0xFFFF0000);
}
});
b_blue.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myView.changePaintColor(0xFF0000FF);
}
});
b_green.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myView.changePaintColor(0xFF00FF00);
}
});
b_orange.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myView.changePaintColor(0xFFFF9900);
}
});
dashBoard = (RelativeLayout) findViewById(R.id.dashBoard);
int width = RelativeLayout.LayoutParams.WRAP_CONTENT;
int hight = RelativeLayout.LayoutParams.WRAP_CONTENT;
myView.setLayoutParams(new RelativeLayout.LayoutParams(width,hight));
dashBoard.addView(myView);
}
public class MyView extends View {
private Paint paint;
private Path path;
public Bitmap mBitmap;
public ProgressDialog pd;
final Point p1 = new Point();
public Canvas canvas;
//Bitmap mutableBitmap ;
public MyView(Context context) {
super(context);
this.paint = new Paint();
this.paint.setAntiAlias(true);
pd = new ProgressDialog(context);
this.paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(5f);
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.unicorn_2).copy(Bitmap.Config.ARGB_8888, true);
//Bitmap.createScaledBitmap(mBitmap, 60, 60 , false);
this.path = new Path();
}
#Override
protected void onDraw(Canvas canvas) {
this.canvas = canvas;
this.paint.setColor(Color.RED);
canvas.drawBitmap(mBitmap, 0, 0, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
p1.x = (int) x;
p1.y = (int) y;
final int sourceColor = mBitmap.getPixel((int) x, (int) y);
final int targetColor = paint.getColor();
new TheTask(mBitmap, p1, sourceColor, targetColor).execute();
invalidate();
}
return true;
}
public void clear() {
path.reset();
invalidate();
}
public int getCurrentPaintColor() {
return paint.getColor();
}
public void changePaintColor(int color){
this.paint.setColor(color);
}
class TheTask extends AsyncTask<Void, Integer, Void> {
Bitmap bmp;
Point pt;
int replacementColor, targetColor;
public TheTask(Bitmap bm, Point p, int sc, int tc) {
this.bmp = bm;
this.pt = p;
this.replacementColor = tc;
this.targetColor = sc;
pd.setMessage("Filling....");
pd.show();
}
#Override
protected void onPreExecute() {
pd.show();
}
#Override
protected void onProgressUpdate(Integer... values) {
}
#Override
protected Void doInBackground(Void... params) {
FloodFill f = new FloodFill();
f.floodFill(bmp, pt, targetColor, replacementColor);
return null;
}
#Override
protected void onPostExecute(Void result) {
pd.dismiss();
invalidate();
}
}
}
// flood fill
public class FloodFill {
public void floodFill(Bitmap image, Point node, int targetColor, int replacementColor) {
int width = image.getWidth();
int height = image.getHeight();
int target = targetColor;
int replacement = replacementColor;
if (target != replacement) {
Queue<Point> queue = new LinkedList<Point>();
do {
int x = node.x;
int y = node.y;
while (x > 0 && image.getPixel(x - 1, y) == target) {
x--;
}
boolean spanUp = false;
boolean spanDown = false;
while (x < width && image.getPixel(x, y) == target) {
image.setPixel(x, y, replacement);
if (!spanUp && y > 0 && image.getPixel(x, y - 1) == target) {
queue.add(new Point(x, y - 1));
spanUp = true;
} else if (spanUp && y > 0 && image.getPixel(x, y - 1) != target) {
spanUp = false;
}
if (!spanDown && y < height - 1 && image.getPixel(x, y + 1) == target) {
queue.add(new Point(x, y + 1));
spanDown = true;
} else if (spanDown && y < (height - 1) && image.getPixel(x, y + 1) != target) {
spanDown = false;
}
x++;
}
} while ((node = queue.poll()) != null);
}
}
}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawingLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<android.support.v7.widget.CardView
android:id="#+id/cardView"
android:layout_width="match_parent"
android:layout_height="542dp"
android:layout_gravity="center"
android:layout_marginTop="8dp"
android:layout_marginRight="8dp"
android:layout_marginLeft="8dp"
android:layout_marginBottom="8dp"
android:background="?android:attr/selectableItemBackground"
app:cardBackgroundColor="#FFFFFF"
app:cardCornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<RelativeLayout
android:id="#+id/dashBoard"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/b_red"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginBottom="10dp" >
</RelativeLayout>
</android.support.v7.widget.CardView>
<Button
android:id="#+id/b_red"
android:layout_width="65dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:background="#FF0000" />
<Button
android:id="#+id/b_green"
android:layout_width="65dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_toRightOf="#+id/b_red"
android:background="#00FF00" />
<Button
android:id="#+id/b_blue"
android:layout_width="65dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_toRightOf="#+id/b_green"
android:background="#0000FF" />
<Button
android:id="#+id/b_orange"
android:layout_width="65dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_toRightOf="#+id/b_blue"
android:background="#FF9900" />
<Button
android:id="#+id/button5"
android:layout_width="60dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:text="Clear" />
Can Someone please help me to fix this

How to put photoview or Imageview inside viewpager android

I am a newbie in android development. I am trying to create an image gallery . While implementing viewpager, I put imageview outside viewpager but because of that I am not able to make zoom and pinch and viewpager work at same time. How can I put imageview inside viewpager ?
FullImageActivity.java:
public class FullImageActivity extends AppCompatActivity {
ImageView images;
int position;
int folderPosition;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_full_image);
Intent i = getIntent();
PhotoView photoView = (PhotoView) findViewById(R.id.photo_view);
photoView.setVisibility(View.GONE);
// Selected image id
position = i.getExtras().getInt("id");
folderPosition = i.getExtras().getInt("folderPosition");
Bundle extras = getIntent().getExtras();
String value = extras.getString("abc");
Glide.with(FullImageActivity.this)
.load(value)
.skipMemoryCache(false)
.into(photoView);
ViewPager mViewPager = (ViewPager) findViewById(R.id.viewpager);
mViewPager.setAdapter(new TouchImageAdapter(this,al_images, folderPosition));
mViewPager.setCurrentItem(position);
}
}
activity_full_image.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/jazzy_pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.github.chrisbanes.photoview.PhotoView
android:id="#+id/photo_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:scaleType="centerCrop"/>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
TouchImageAdapter.java
class TouchImageAdapter extends PagerAdapter {
Context context;
String filename;
ArrayList<Model_images> al_menu = new ArrayList<>();
int position,int_position;
public TouchImageAdapter(Context context,ArrayList<Model_images> al_menu, int position){
this.al_menu = al_menu;
this.context = context;
this.int_position = position;
}
#Override
public int getCount() {
return al_menu.get(int_position).getAl_imagepath().size();
}
#Override
public View instantiateItem(ViewGroup container, int position) {
ImageView img = new ImageView(container.getContext());
ViewGroup.LayoutParams lp= new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
img.setLayoutParams(lp);
img.setImageDrawable(getImageFromSdCard(filename,position));
container.addView(img, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
return img;
}
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
public Drawable getImageFromSdCard(String imageName,int position) {
Drawable d = null;
try {
String path = al_menu.get(int_position).getAl_imagepath().get(position)
+ "/";
Bitmap bitmap = BitmapFactory.decodeFile(path);
d = new BitmapDrawable(context.getResources(),bitmap);
} catch (IllegalArgumentException e) {
// TODO: handle exception
}
return d;
}
}
Use this custom TouchImageView instead of imageview
public class TouchImageView extends ImageView {
private void stopInterceptEvent()
{
getParent().requestDisallowInterceptTouchEvent(true);
}
private void startInterceptEvent()
{
getParent().requestDisallowInterceptTouchEvent(false);
}
private void sharedConstructing(Context context) {
super.setClickable(true);
this.context = context;
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
matrix.setTranslate(1f, 1f);
m = new float[9];
setImageMatrix(matrix);
setScaleType(ScaleType.MATRIX);
setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
mScaleDetector.onTouchEvent(event);
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
PointF curr = new PointF(event.getX(), event.getY());
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
last.set(event.getX(), event.getY());
start.set(last);
mode = DRAG;
stopInterceptEvent();
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
float deltaX = curr.x - last.x;
float deltaY = curr.y - last.y;
float scaleWidth = Math.round(origWidth * saveScale);
float scaleHeight = Math.round(origHeight * saveScale);
if (scaleWidth < width) {
deltaX = 0;
if (y + deltaY > 0)
deltaY = -y;
else if (y + deltaY < -bottom)
deltaY = -(y + bottom);
} else if (scaleHeight < height) {
deltaY = 0;
if (x + deltaX > 0)
deltaX = -x;
else if (x + deltaX < -right)
deltaX = -(x + right);
} else {
if (x + deltaX > 0)
deltaX = -x;
else if (x + deltaX < -right)
deltaX = -(x + right);
if (y + deltaY > 0)
deltaY = -y;
else if (y + deltaY < -bottom)
deltaY = -(y + bottom);
}
if(deltaX == 0)
startInterceptEvent();
else
stopInterceptEvent();
matrix.postTranslate(deltaX, deltaY);
last.set(curr.x, curr.y);
}
break;
case MotionEvent.ACTION_UP:
mode = NONE;
int xDiff = (int) Math.abs(curr.x - start.x);
int yDiff = (int) Math.abs(curr.y - start.y);
if (xDiff < CLICK && yDiff < CLICK)
performClick();
startInterceptEvent();
break;
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
}
setImageMatrix(matrix);
invalidate();
return true; // indicate event was handled
}
});
}
}
Also change your activity_full_xml like this
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TouchImageView
android:id="#+id/photo_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:scaleType="centerCrop"/>
</android.support.v4.view.ViewPager>

how to dispatch touch events or rewrite onTouchEvent when use a scollview in viewpager?

I create a vertical viewpager like this:
/**
* Swaps the X and Y coordinates of your touch event.
*/
private MotionEvent swapXY(MotionEvent ev) {
float width = getWidth();
float height = getHeight();
float newX = (ev.getY() / height) * width;
float newY = (ev.getX() / width) * height;
ev.setLocation(newX, newY);
return ev;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev){
boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
swapXY(ev);
return intercepted;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
return super.onTouchEvent(swapXY(ev));
}
and in the second fragment create a common viewpager with 4 fragments,and so far everything goes well,no conflicts.
Well, I put scrollviews into 3 of them,and this time when I try to scroll to the top fragment of my vertical viewpager it doesn't work with my first touch in scrollview(If I touch the other parts of this fragment it won't happen).
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/transparent"
android:orientation="horizontal"
android:layout_marginBottom="120dp"
android:paddingLeft="5dp"
android:paddingRight="5dp" >
<com.nangua.xiaomanjflc.widget.SmartScrollView
android:id="#+id/sv"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/ll_project_profile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/white"
android:orientation="vertical"
android:paddingBottom="#dimen/page_bottom"
android:paddingTop="#dimen/page_small"
android:visibility="visible" >
<TextView
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="#dimen/page_line"
android:lineSpacingMultiplier="1.2"
android:textColor="#color/font_gray"
android:textSize="#dimen/font_hint" />
</LinearLayout>
</com.nangua.xiaomanjflc.widget.SmartScrollView>
</LinearLayout>
What I want is that when I scroll the scrollview over the top, it can be moved softly like my vertical viewpager does.Once I rewrited the onTouchEvent of my vertical viewpager,common viewpager and scrollview found that vertical MotionEvent action was catched by common viewpager and gone so that vertical viewpager catched nothing.
Now here's my bad solution that I put a callback in the scrollview when it scrolled to top ,the outside handle will noticed my vertical viewpager,and it scroll to the top fragment with calling setCurrentItem(0) method.But actually it seems so weird.
So what should I do when rewriting the onInterceptTouchEvent, onTouchEvent or some other useful methods of the conflicted 3 parts?
the scrollview's codes:
public SmartScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
private ISmartScrollChangedListener mSmartScrollChangedListener;
public interface ISmartScrollChangedListener {
void onScrolledToBottom();
void onScrolledToTop();
}
public void setScanScrollChangedListener(
ISmartScrollChangedListener smartScrollChangedListener) {
mSmartScrollChangedListener = smartScrollChangedListener;
}
#Override
protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX,
boolean clampedY) {
super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
if (scrollY == 0) {
isScrolledToTop = clampedY;
isScrolledToBottom = false;
}
else {
isScrolledToTop = false;
isScrolledToBottom = clampedY;
}
notifyScrollChangedListeners();
}
#Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (getScrollY() == 0) {
isScrolledToTop = true;
isScrolledToBottom = false;
}
else if (getScrollY() + getHeight() - getPaddingTop()
- getPaddingBottom() == getChildAt(0).getHeight()) {
isScrolledToBottom = true;
isScrolledToTop = false;
}
else {
isScrolledToTop = false;
isScrolledToBottom = false;
}
notifyScrollChangedListeners();
}
}
private void notifyScrollChangedListeners() {
if (isScrolledToTop) {
if (mSmartScrollChangedListener != null) {
mSmartScrollChangedListener.onScrolledToTop();
}
}
else if (isScrolledToBottom) {
if (mSmartScrollChangedListener != null) {
mSmartScrollChangedListener.onScrolledToBottom();
}
}
}
public boolean isScrolledToTop() {
return isScrolledToTop;
}
public boolean isScrolledToBottom() {
return isScrolledToBottom;
}
public boolean canScroll() {
View child = getChildAt(0);
if (child != null) {
int childHeight = child.getHeight();
return getHeight() < childHeight;
}
return false;
}

Move ImageView elliptically around a center in a RelativeView

I have a setup in which I have some ImageViews around a center, and when the user clicks a Button, I want the Views to rotate around the center view, in an elliptical way.
What I have at current time is an elliptical movement, but the view is rotating in a weird axis, not on the center axis, as required.
<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="com.didasko.calculus.maca.TelaAtomo"
>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tela_atomo_maca_central"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:src="#drawable/maca_cinza"
android:background="#null"/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tela_atomo_eletron_0"
android:src="#drawable/eletron_nao_completado"
android:background="#null"
android:layout_marginRight="46dp"
android:layout_toLeftOf="#+id/tela_atomo_maca_central"
android:layout_marginBottom="78dp"
android:layout_above="#+id/tela_atomo_maca_central"/>
</RelativeLayout>
tela_atomo_maca_central is the center element
tela_atomo_eletron_0 is the view I want to move elliptically
final ImageButton eletron = (ImageButton) findViewById(R.id.tela_atomo_eletron_0);
//Getting all points in the ellipse
for(int i=0;i<360;i++) {
double x = 46 * Math.cos(i);
double y = 78 * Math.sin(i);
Ponto p = new Ponto(x,y);
pontos.add(p);
}
Runnable eletronRunnable = new Runnable() {
#Override
public void run() {
if (contagem < 360) {
Ponto p = pontos.get(contagem);
contagem++;
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) eletron.getLayoutParams();
params.rightMargin = (int)p.getX();
params.bottomMargin = (int)p.getY();
eletron.setLayoutParams(params);
eletron.postDelayed(this,100);
}else {
contagem = 0;
eletron.postDelayed(this,100);
}
}
};
eletron.postDelayed(eletronRunnable,100);
}
private class Ponto {
private double x,y;
public Ponto(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
}
I'm probably making logical mistakes, because I can make it move elliptically, just not where I want.
How can I make the Image move elliptically around the center?
Based on your existing code I made a sample project and here is what I acheived -
Here is the modified code -
public class ActivityTest extends AppCompatActivity {
ImageButton eletron,center;
ArrayList<Ponto> pontos = new ArrayList<>();
int contagem = 0;
DemoRelativeLayout rel;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.so_demo);
eletron = (ImageButton) findViewById(R.id.tela_atomo_eletron_0);
center = (ImageButton) findViewById(R.id.tela_atomo_maca_central);
rel = (DemoRelativeLayout)findViewById(R.id.demo);
//Getting all points in the ellipse
for(int i=0;i<360;i++) {
double x = (200 * Math.cos(i));
double y = (400 * Math.sin(i));
Ponto p = new Ponto(x,y);
pontos.add(p);
}
eletron.postDelayed(eletronRunnable,2000);
}
#Override
protected void onStart() {
super.onStart();
rel.drawCircle(pontos,center.getX() + center.getWidth()/2,center.getY() + center.getHeight()/2);
rel.invalidate();
}
Runnable eletronRunnable = new Runnable() {
#Override
public void run() {
if (contagem < 360) {
Ponto p = pontos.get(contagem);
contagem++;
/*RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) eletron.getLayoutParams();
params.rightMargin = (int)p.getX();
params.bottomMargin = (int)p.getY();
eletron.setLayoutParams(params);*/
eletron.setTranslationX((float) p.getX() + (eletron.getWidth()/2 + center.getWidth()/2));
eletron.setTranslationY((float)p.getY() + (eletron.getHeight()/2 + center.getHeight()/2));
eletron.postDelayed(this,100);
}else {
contagem = 0;
eletron.postDelayed(this,100);
}
}
};
public class Ponto {
private double x,y;
public Ponto(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
}
}
I have also changed the xml file -
<com.wandertails.stackovrflw.DemoRelativeLayout
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:padding="10dp"
android:background="#ffffff"
android:id="#+id/demo"
>
<ImageButton
android:layout_width="40dp"
android:layout_height="40dp"
android:id="#+id/tela_atomo_maca_central"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:src="#444444"
android:background="#null"/>
<ImageButton
android:layout_width="40dp"
android:layout_height="40dp"
android:id="#+id/tela_atomo_eletron_0"
android:src="#880080"
android:background="#null"
android:layout_toLeftOf="#+id/tela_atomo_maca_central"
android:layout_above="#+id/tela_atomo_maca_central"/>
</com.wandertails.stackovrflw.DemoRelativeLayout>
Finally the DemoRelativeLayout if you want to draw the elliptical path -
public class DemoRelativeLayout extends RelativeLayout
{
ArrayList<ActivityTest.Ponto> pontos;
float cntrX,cntrY;
public DemoRelativeLayout(Context context) {
super(context);
}
public DemoRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DemoRelativeLayout(Context context, AttributeSet attrs, intdefStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if(pontos != null){
Paint p = new Paint();
p.setColor(Color.RED);
for (ActivityTest.Ponto pt : pontos){
float x = (float)pt.getX() + cntrX;
float y = (float)pt.getY() + cntrY;
canvas.drawCircle(x,y,5,p);
}
}
}
public void drawCircle(ArrayList<ActivityTest.Ponto> pp,float x,float y){
cntrX = x;
cntrY = y;
pontos = pp;
}
}
I hope this is all you want..

Rotating around two points in android not working

I have two seperate (x, y) points that I want to use to apply rotation to a view.
The first point is fixed, and I find the values of it fairly easily (for example 200,200). My second point is where a TOUCH is present, so I grab the RawX and RawY points easily as well. I feed these two points into this method that I found on another stack overflow question.
private float findRotation(int firstPointX, int firstPointY, int secondPointX, int secondPointY) {
double delta_x = (firstPointX - secondPointX);
double delta_y = (firstPointY - secondPointY);
double radians = Math.atan2(delta_y, delta_x);
return (float) Math.toDegrees(radians);
}
and I use the return of that to set the rotation of a View. Like so myView.setRotation(...). The result ends up being a crazy spinning view while I move the cursor/finger on the screen. Any ideas?
The two points I'm grabbing seem to be correct, leaving me guessing that maybe the findRotation method is incorrect.
My activity:
public class MainActivity extends Activity {
ImageView imageView;
ImageView dragHandle;
RelativeLayout layout;
int rememberAngle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.imageView1);
dragHandle = (ImageView) findViewById(R.id.imageView2);
layout = (RelativeLayout) findViewById(R.id.relativeLayout2);
resize(dragHandle);
}
public void resize(ImageView resizeButton) {
resizeButton.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
int[] locationOfLayout = new int[2];
int[] locationOfDrag = new int[2];
layout.getLocationOnScreen(locationOfLayout);
dragHandle.getLocationOnScreen(locationOfDrag);
int firstPointX = locationOfLayout[0];
int firstPointY = locationOfLayout[1];
int secondPointX = dragHandle.getWidth() / 2 + locationOfDrag[0];
int secondPointY = dragHandle.getHeight() / 2 + locationOfDrag[1];
rememberAngle = (int) findRotation(firstPointX, firstPointY, secondPointX, secondPointY) + layout.getRotation();
} else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
int[] locationOfLayout = new int[2];
int[] locationOfDrag = new int[2];
layout.getLocationOnScreen(locationOfLayout);
dragHandle.getLocationOnScreen(locationOfDrag);
int centerXOnLayout = layout.getWidth() / 2 + locationOfLayout[0];
int centerYOnLayout = layout.getHeight() / 2 + locationOfLayout[1];
int centerXOnDrag = dragHandle.getWidth() / 2 + locationOfDrag[0];
int centerYOnDrag = dragHandle.getHeight() / 2 + locationOfDrag[1];
layout.setRotation(findRotation(centerXOnLayout, centerYOnLayout, centerXOnDrag, centerYOnDrag) - rememberAngle);
} else if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
}
return true;
}
});
}
private float findRotation(int firstPointX, int firstPointY, int secondPointX, int secondPointY) {
double delta_x = (secondPointX - firstPointX);
double delta_y = (secondPointY - firstPointY);
double radians = Math.atan2(delta_y, delta_x);
return (float) Math.toDegrees(radians);
}
}
My 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" >
<RelativeLayout
android:id="#+id/relativeLayout2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="#drawable/ic_launcher" />
<ImageView
android:id="#+id/imageView2"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_below="#+id/imageView1"
android:layout_toRightOf="#+id/imageView1"
android:src="#drawable/meanicons" />
</RelativeLayout>
</RelativeLayout>
public void resize(ImageView resizeButton) {
resizeButton.setOnTouchListener(new View.OnTouchListener() {
float startAngle;
float zeroAngle;
int firstPointX;
int firstPointY;
public boolean onTouch(View v, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
int[] locationOfLayout = new int[2];
int[] locationOfDrag = new int[2];
layout.getLocationOnScreen(locationOfLayout);
dragHandle.getLocationOnScreen(locationOfDrag);
firstPointX = locationOfLayout[0];
firstPointY = locationOfLayout[1];
int secondPointX = motionEvent.getRawX();
int secondPointY = motionEvent.getRawY();
zeroAngle = findRotation(firstPointX, firstPointY, secondPointX, secondPointY) // remember "zero" angle
startAngle = layout.getRotation(); // remember angle at which layout is rotated at the start
} else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
layout.setRotation(findRotation(firstPointX, firstPointY, motionEvent.getRawX(), motionEvent.getRawY()) - zeroAngle + startAngle); // rotate relative to start and zero angle
} else if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
}
return true;
}
});
}
private float findRotation(int firstPointX, int firstPointY, int secondPointX, int secondPointY) {
double delta_x = (secondPointX - firstPointX);
double delta_y = (secondPointY - firstPointY);
double radians = Math.atan2(delta_y, delta_x);
return (float) Math.toDegrees(radians);
}

Categories