Android PullTo Refresh on ScrollView - android

I know that pullToRefresh like functionality is available in the iPhone and for the Android we have to manage it manually.
I got some example the having pullToRefresh but it works on the ListView only.
In my case I want to implement for the Scrollview. Something like PullToRefresh available in DrawFree app in Google Play.
Please see below image:
So, how to implement it?

This is a excellent example of implementing pull to refresh in ListView, GridView, WebView, Expandable ListView.
You can use this example and make changes according to your Views.
https://github.com/chrisbanes/Android-PullToRefresh

[EDIT: my solution is Gmail-like, I'm sorry if it's not exactly what you want, anyway I post the code that may be usefull for others]
I've just done it, I've already implemented it in a ListView following the example written by Joe Dailey (very good and simple). Then I revisited it to be used with ScrollView.
This is what I've done:
I set an onTouchListener to the ScrollView;
I control if the scrollView is on top (scrollView.getScrollY() == 0)
Then, I use "lastY = startY" to know if I'm scrolling down or up (both the variables are activity fields).
"act.refresh()" is the method that runs the task to get data from my server.
In the onPostExecute method of your asynkTask, or in the Handler if you use hanlders, you call "finishRefresh()" method;
this is the onTouchListener:
class RefreshTouchListener implements View.OnTouchListener {
#Override
public boolean onTouch(View v, MotionEvent event) {
ScrollView scroll = (ScrollView) v;
if (scroll.getScrollY() == 0) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startY = event.getY();
lastY = startY;
break;
case MotionEvent.ACTION_MOVE:
if (!refreshing && event.getY() > lastY) {
lastY = event.getY();
if (event.getY() - startY <= dragLength) {
double percent = 1 - (event.getY() - startY) / dragLength;
double weight;
weight = 2 * Math.pow(percent, 0.8);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) progress.getLayoutParams();
params.weight = (float) weight;
progress.setLayoutParams(params);
progress.setIndeterminate(false);
progress.setPadding(0, 0, 0, 0);
return true;
} else {
refreshing = true;
act.refresh();
startY = 100000f;
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) progress.getLayoutParams();
params.weight = 0;
progress.setIndeterminate(true);
progress.postInvalidate();
progress.setLayoutParams(params);
}
}
case MotionEvent.ACTION_UP:
startY = 100000f;
Log.i(TAG, "action up " + event.getY());
if (!refreshing) {
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) progress.getLayoutParams();
params.weight = 2;
progress.setLayoutParams(params);
}
}
}
return false;
}
}
this is the finishRefresh() method:
public void finishRefresh() {
progress.setIndeterminate(false);
progress.postInvalidate();
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) progress.getLayoutParams();
params.weight = 2;
progress.setLayoutParams(params);
refreshing = false;
}
this is the code to generate the layout, with the progressBar and everything else:
private void createProgressBarLayout() {
topMargin = -Math.round(6 * act.metrics.density);
dragLength = Math.round(act.screen_size.y / 2.5f);
LinearLayout top = new LinearLayout(this);
top.setGravity(Gravity.TOP);
top.setOrientation(LinearLayout.HORIZONTAL);
content_rel_layout = (RelativeLayout) findViewById(R.id.rel_layout_name);
content_rel_layout.addView(top);
ViewGroup.LayoutParams topParams = top.getLayoutParams();
topParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
topParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
top.setLayoutParams(topParams);
FrameLayout left = new FrameLayout(this);
progress = new ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal);
progress.setProgress(100);
progress.setIndeterminate(false);
// progress.setBackgroundResource(R.drawable.progress_bar);
FrameLayout right = new FrameLayout(this);
top.addView(left);
top.addView(progress);
top.addView(right);
LinearLayout.LayoutParams leftParams = (LinearLayout.LayoutParams) left.getLayoutParams();
leftParams.weight = 1;
leftParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
leftParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
leftParams.topMargin = topMargin;
left.setLayoutParams(leftParams);
LinearLayout.LayoutParams progressParams = (LinearLayout.LayoutParams) progress.getLayoutParams();
progressParams.weight = 2;
progressParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
progressParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
progressParams.topMargin = topMargin;
progress.setLayoutParams(progressParams);
LinearLayout.LayoutParams rightParams = (LinearLayout.LayoutParams) right.getLayoutParams();
rightParams.weight = 1;
rightParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
rightParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
rightParams.topMargin = topMargin;
right.setLayoutParams(rightParams);
ScrollView sv = (ScrollView) findViewById(R.id.prof_mon4_vert_scroll);
sv.setOnTouchListener(new RefreshTouchListener());
}
Please feel free to ask me for every doubt!
Enjoy

Related

Resizing a view based on the distance between start drag and end drag

I am working on a project where I have a view, which, once clicked, instantiates a class, passing the view to the constructor, which creates 4 anchor points on to the view. This is done using the following:
customView = new CustomView(MainActivity.this, viewCounter,
customView.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Resizer resizer = new Resizer(MainActivity.this, MainActivity.this, container, customView, lblStatus);
}
});
The resizer class is as follows:
public Resizer(Context context, AppCompatActivity activity, ViewGroup container, ViewGroup viewToBeResized, TextView lblStatus)
{
this.context = context;
this.activity = activity;
this.container = container;
this.viewToBeResized = viewToBeResized;
this.lblStatus = lblStatus;
createAnchorPoints();
}
private void createAnchorPoints()
{
Drawable circle = ContextCompat.getDrawable(context, R.drawable.anchor);
int circleSize = dpToPx(CIRCLE_SIZE_DP);
Anchor topLeftAnchor = new Anchor(context, viewToBeResized, Anchor.ResizeMode.TOP_LEFT, lblStatus);
topLeftAnchor.setImageDrawable(circle);
RelativeLayout.LayoutParams topLeftParms = new RelativeLayout.LayoutParams(circleSize, circleSize);
topLeftParms.addRule(RelativeLayout.ALIGN_PARENT_START, viewToBeResized.getId());
topLeftParms.addRule(RelativeLayout.ALIGN_PARENT_TOP, viewToBeResized.getId());
viewToBeResized.addView(topLeftAnchor, topLeftParms);
Anchor topRightAnchor = new Anchor(context, viewToBeResized, Anchor.ResizeMode.TOP_RIGHT, lblStatus);
topRightAnchor.setImageDrawable(circle);
RelativeLayout.LayoutParams topRightParms = new RelativeLayout.LayoutParams(circleSize, circleSize);
topRightParms.addRule(RelativeLayout.ALIGN_PARENT_END, viewToBeResized.getId());
topRightParms.addRule(RelativeLayout.ALIGN_PARENT_TOP, viewToBeResized.getId());
viewToBeResized.addView(topRightAnchor, topRightParms);
Anchor bottomLeftAnchor = new Anchor(context, viewToBeResized, Anchor.ResizeMode.BOTTOM_RIGHT, lblStatus);
bottomLeftAnchor.setImageDrawable(circle);
RelativeLayout.LayoutParams bottomLeftParms = new RelativeLayout.LayoutParams(circleSize, circleSize);
bottomLeftParms.addRule(RelativeLayout.ALIGN_PARENT_START, viewToBeResized.getId());
bottomLeftParms.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, viewToBeResized.getId());
viewToBeResized.addView(bottomLeftAnchor, bottomLeftParms);
Anchor bottomRightAnchor = new Anchor(context, viewToBeResized, Anchor.ResizeMode.BOTTOM_RIGHT, lblStatus);
bottomRightAnchor.setImageDrawable(circle);
RelativeLayout.LayoutParams bottomRightParms = new RelativeLayout.LayoutParams(circleSize, circleSize);
bottomRightParms.addRule(RelativeLayout.ALIGN_PARENT_END, viewToBeResized.getId());
bottomRightParms.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, viewToBeResized.getId());
viewToBeResized.addView(bottomRightAnchor, bottomRightParms);
}
In the anchor class that gets created at each corner, a touch listener is used. What I am trying to do is as the user drags the anchor view, the main view, that is passed into the anchor, will resize in the direction the user dragged.
Below is my touch listener
public class AnchorTouchListener implements View.OnTouchListener
{
private int _xDelta;
private int _yDelta;
private View viewToResize;
private TextView lblStatus;
private Anchor.ResizeMode resizeMode;
public AnchorTouchListener(View viewToResize, TextView lblStatus, Anchor.ResizeMode resizeMode)
{
this.viewToResize = viewToResize;
this.lblStatus = lblStatus;
this.resizeMode = resizeMode;
}
#Override
public boolean onTouch(View view, MotionEvent event)
{
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
Log.d("Anchor", "Updating X & Y");
int diff = 0;
switch (event.getAction() & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN:
lblStatus.setText("Moving down");
RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
_xDelta = X - lParams.leftMargin;
_yDelta = Y - lParams.topMargin;
break;
case MotionEvent.ACTION_UP:
lblStatus.setText("Drag finished");
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
lblStatus.setText("Moving around");
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
layoutParams.leftMargin = X - _xDelta;
layoutParams.topMargin = Y - _yDelta;
layoutParams.rightMargin = _xDelta - X;
layoutParams.bottomMargin = _yDelta - Y;
view.setLayoutParams(layoutParams);
//viewToResize.animate().scaleX(0.6f);
if (resizeMode == Anchor.ResizeMode.BOTTOM_RIGHT)
{
diff = diff - X - _xDelta;
Log.d("Anchor Touch", "Diff: " + diff);
if (diff > 0)
{
((RelativeLayout.LayoutParams) viewToResize.getLayoutParams()).width = viewToResize.getLayoutParams().width + Math.abs(diff);
}
else
{
((RelativeLayout.LayoutParams)viewToResize.getLayoutParams()).width = viewToResize.getLayoutParams().width - Math.abs(diff);
}
}
break;
}
return true;
}
}
It is kind of working, except its not moving smoothly with the anchor, the view being resized seems to grow quicker than what is being dragged and is very erratic at how it resize and shrinks.
Is there a better way for doing what I am trying to achieve or can anyone see what I might be doing wrong.
UPDATE
Added video to show what I am trying to achieve and what the problem is.
Since the anchors are positioned with a RelativeLayout, there is no need to write code to move the anchors. Simply resize the grey box and the anchors will be positioned correctly upon layout. The size of the grey box can be determined by capturing initial conditions of the pointer placement and the initial size of the box to achieve the following.
I have only implemented the bottom right anchor and I have taken some liberties with your implementation, but the concept is still valid for your code and the other anchor points.
AnchorTouchListener.java
public class AnchorTouchListener implements View.OnTouchListener {
private int _xDelta;
private int _yDelta;
private View viewToResize;
private TextView lblStatus;
// private Anchor.ResizeMode resizeMode;
public AnchorTouchListener(View viewToResize, TextView lblStatus/*, Anchor.ResizeMode resizeMode*/) {
this.viewToResize = viewToResize;
this.lblStatus = lblStatus;
// this.resizeMode = resizeMode;
}
private int initialHeight;
private int initialWidth;
private int initialX;
private int initialY;
#Override
public boolean onTouch(View view, MotionEvent event) {
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
Log.d("Anchor", "Updating X & Y");
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
lblStatus.setText("Action down");
// Capture initial conditions of the view to resize.
initialHeight = viewToResize.getHeight();
initialWidth = viewToResize.getWidth();
// Capture initial touch point.
initialX = X;
initialY = Y;
break;
case MotionEvent.ACTION_UP:
lblStatus.setText("Drag finished");
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
lblStatus.setText("Moving around");
RelativeLayout.LayoutParams lp =
(RelativeLayout.LayoutParams) viewToResize.getLayoutParams();
// Compute how far we have moved in the X/Y directions.
_xDelta = X - initialX;
_yDelta = Y - initialY;
// Adjust the size of the targeted view. Note that we don't have to position
// the resize handle since it will be positioned correctly due to the layout.
lp.width = initialWidth + _xDelta;
lp.height = initialHeight + _yDelta;
viewToResize.setLayoutParams(lp);
break;
}
return true;
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Drawable circle = ContextCompat.getDrawable(this, R.drawable.circle);
ImageView imageView = new ImageView(this);
imageView.setImageDrawable(circle);
int circleSize = dpToPx(CIRCLE_SIZE_DP);
RelativeLayout viewToBeResized = findViewById(R.id.customView);
ImageView bottomRightAnchor = new ImageView(this);
bottomRightAnchor.setImageDrawable(circle);
RelativeLayout.LayoutParams bottomRightParms =
new RelativeLayout.LayoutParams(circleSize, circleSize);
bottomRightParms.addRule(RelativeLayout.ALIGN_PARENT_END, viewToBeResized.getId());
bottomRightParms.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, viewToBeResized.getId());
viewToBeResized.addView(bottomRightAnchor, bottomRightParms);
bottomRightAnchor.setOnTouchListener(
new AnchorTouchListener(viewToBeResized, ((TextView) findViewById(R.id.status))));
}
private int dpToPx(int dp) {
return (int) (dp * getResources().getDisplayMetrics().density);
}
private static final int CIRCLE_SIZE_DP = 20;
}
activity_main.xml
<RelativeLayout
android:id="#+id/relativeLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<RelativeLayout
android:id="#+id/customView"
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#android:color/holo_green_light" />
<TextView
android:id="#+id/status"
android:layout_width="wrap_content"
tools:text="Status"
android:layout_height="wrap_content" />
</RelativeLayout>
RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
In above line of code in your AnchorTouchListener class you are getting the params of the view endpoint you created earlier.
Getting the correct LayourParams should solve the problem.

google chrome animation effect in android

I am trying create animation just like used in google chrome when opening 2 or more tabs. Here is the image below.
How could I do make this effect as in google chrome. They animated like SlidingDrawer (but it is not a slidingDrawer as far as I know.)
It is not exactly as Google chrome effect but maybe helpful someone in the future.
public class MyActivity extends Activity implements View.OnTouchListener {
ViewGroup _root;
private int _xDelta;
private int _yDelta;
LinearLayout relativeLayout1;
LinearLayout relativeLayout2;
LinearLayout relativeLayout3;
LinearLayout relativeLayout4;
LinearLayout relativeLayout5;
LinearLayout relativeLayout6;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main3);
_root = (ViewGroup)findViewById(R.id.root);
relativeLayout1 = new LinearLayout(this);
relativeLayout2 = new LinearLayout(this);
relativeLayout3 = new LinearLayout(this);
relativeLayout4 = new LinearLayout(this);
relativeLayout5 = new LinearLayout(this);
relativeLayout6 = new LinearLayout(this);
relativeLayout1.setOrientation(LinearLayout.VERTICAL);
relativeLayout2.setOrientation(LinearLayout.VERTICAL);
relativeLayout3.setOrientation(LinearLayout.VERTICAL);
relativeLayout4.setOrientation(LinearLayout.VERTICAL);
relativeLayout5.setOrientation(LinearLayout.VERTICAL);
relativeLayout6.setOrientation(LinearLayout.VERTICAL);
relativeLayout1.setId(1);
relativeLayout2.setId(2);
relativeLayout3.setId(3);
relativeLayout4.setId(4);
relativeLayout5.setId(5);
relativeLayout6.setId(6);
relativeLayout1.setBackgroundColor(Color.RED);
relativeLayout2.setBackgroundColor(Color.BLUE);
relativeLayout3.setBackgroundColor(Color.GREEN);
relativeLayout4.setBackgroundColor(Color.GRAY);
relativeLayout5.setBackgroundColor(Color.CYAN);
relativeLayout6.setBackgroundColor(Color.DKGRAY);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 300);
relativeLayout1.setLayoutParams(layoutParams);
_root.addView(relativeLayout1);
RelativeLayout.LayoutParams layoutParams1 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 300);
// relativeLayout1.setOnTouchListener(this); // first element have to stay fixed
relativeLayout2.setOnTouchListener(this);
relativeLayout3.setOnTouchListener(this);
relativeLayout4.setOnTouchListener(this);
relativeLayout5.setOnTouchListener(this);
relativeLayout6.setOnTouchListener(this);
relativeLayout2.setLayoutParams(layoutParams1);
relativeLayout3.setLayoutParams(layoutParams1);
relativeLayout4.setLayoutParams(layoutParams1);
relativeLayout5.setLayoutParams(layoutParams1);
relativeLayout6.setLayoutParams(layoutParams1);
_root.addView(relativeLayout2);
_root.addView(relativeLayout3);
_root.addView(relativeLayout4);
_root.addView(relativeLayout5);
_root.addView(relativeLayout6);
}
public boolean onTouch(View view, MotionEvent event) {
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
LinearLayout.LayoutParams lParams = (LinearLayout.LayoutParams) view.getLayoutParams();
// _xDelta = X - lParams.leftMargin;
_yDelta = Y - lParams.topMargin;
// System.out.println("getRawY"+(int)event.getRawY());
System.out.println("DOWN=="+_yDelta);
System.out.println("view height=="+ view.getHeight());
System.out.println("root view="+_root.getHeight());
break;
case MotionEvent.ACTION_UP:
System.out.println("getRawY="+(int)event.getRawY());
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
System.out.println("getRawYMOVE="+(int)event.getRawY());
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) view.getLayoutParams();
// layoutParams.leftMargin = X - _xDelta;
int dif = Y - _yDelta;
if (view.getHeight() + (dif) > 30){
if (dif < 0 && Math.abs(dif) >= view.getHeight()/5){
layoutParams.topMargin = dif;
view.setLayoutParams(layoutParams);
} else if (dif <= 0 && dif < view.getHeight()/5){
layoutParams.topMargin = dif;
view.setLayoutParams(layoutParams);
}
View p_view = findViewById(view.getId() - 1);
if (p_view.getId() != 1){
p_view.setLayoutParams(layoutParams);
}
}
break;
}
_root.invalidate();
return true;
}
}

How to set OnTouchListener for dynamically created views?

I have two layouts, one LinearLayout and one RelativeLayout. In the LinearLayout I have 10 images. When I click one image, it is added to the RelativeLayout. Similar event is given for all 10 images. In the RelativeLayout, I have set a OnTouchListener to the ImageView added from the LinearLayout. But my problem is, onTouch only works for the ImageView which is recently added but when I try to touch previously added images, it doesn't work. I want to add listener for all images added in the relative layout.
Below is what I have tried so far:
for(int i = 0; i < data.length; i++){
image[i] = new ImageView(getApplicationContext());
try{
// int imgID = getResources().getIdentifier(data[i], null, getPackageName());
image[i].setImageResource(data[i]);
}catch(Exception e){
int imgID = getResources().getIdentifier("nia", "drawable", "package");
image[i].setImageResource(imgID);
}
LinearLayout.LayoutParams LEye = new LinearLayout.LayoutParams(
100 , 70);
LEye.leftMargin=20;
image[i].setLayoutParams(LEye);
shapeImageContainer.addView(image[i]); //shapeImageContainer is the Linear Layout
final int c=i;
image[i].setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
//addContentView( addIcon(), new RelativeLayout.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT ) );
Toast.makeText(NewProject.this, "Position "+c, Toast.LENGTH_SHORT).show();
rootView.addView(addIcon(c)); //rootView is the Relative layout
}
});
//image[i].setOnTouchListener(MyOnTouchListener);
}
private ImageView addIcon(int c){
item = new ImageView(this);
item.setImageResource(data[c]);
item.setAdjustViewBounds(true);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(100, 60 );
if( mIconIdCounter != 1 ){
params.addRule(RelativeLayout.RIGHT_OF,c-1);
}
item.setLayoutParams( params );
item.setId( mIconIdCounter );
++mIconIdCounter;
item.setOnTouchListener(MyOnTouchListener);
return item;
}
OnTouchListener MyOnTouchListener = new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
// scroll.setEnabled(false);
// horizontal.setEnabled(false);
// scroll.setVisibility(View.GONE);
// horizontal.setVisibility(View.GONE);
RelativeLayout.LayoutParams layoutParams2 = (RelativeLayout.LayoutParams) item.getLayoutParams();
switch(event.getActionMasked())
{
case MotionEvent.ACTION_MOVE:
scroll.requestDisallowInterceptTouchEvent(true);
horizontal.requestDisallowInterceptTouchEvent(true);
int x_cord = (int) event.getRawX();
int y_cord = (int) event.getRawY();
//right margin
if (x_cord > windowwidth) {
x_cord = windowwidth-10;
}
// left margin original
if (x_cord <68) {
x_cord = 68;
}
// left margin original
if (y_cord <68) {
y_cord = 68;
}
if (y_cord > windowheight) {
y_cord = windowheight-10;
}
// tv.setText(String.valueOf(y_cord));
layoutParams2.leftMargin = x_cord -60;
layoutParams2.topMargin = y_cord -65;
item.setLayoutParams(layoutParams2);
break;
default:
break;
}
return true;
}
};
But my problem is, onTouch only works for the imageview which is
recently added but when I try to touch previously added images,it
doesn't work.
That's because in the OnTouchListener you use the item field to do your work(which will always point to the last ImageView added as you wrote the code) instead of using the View for which the listener is called. Try something like this:
RelativeLayout.LayoutParams layoutParams2 = (RelativeLayout.LayoutParams) v.getLayoutParams();
// rest of the onTouch callback...
v.setLayoutParams(layoutParams2);

How to change the position of a imageButton when onClick

I am trying to shift the position of a image button when on click. I tried the following but it crashes at "rlOut.addView(imgP, p);" I have no issues when running them in onCreate().
public class Delet3Activity extends Activity {
RelativeLayout rlOut;
ImageButton imbBtn;
EditText et1, et2;
ImageView ivB;
ImageButton imgP;
RelativeLayout.LayoutParams p;
RelativeLayout.LayoutParams params;
int mX, mY;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
et1 = (EditText)findViewById(R.id.et1);
et2 = (EditText)findViewById(R.id.et2);
imbBtn = (ImageButton)findViewById(R.id.imgBtn);
rlOut = (RelativeLayout)findViewById(R.id.rlOut);
imgP = (ImageButton)findViewById(R.id.imgP);
ivB = new ImageView(this);
ivB.setBackgroundColor(Color.RED);
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
width = width/2-62;
height = height/2-62;
p = new RelativeLayout.LayoutParams(62, 62);
imbBtn.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
LayoutParams par = (LayoutParams)imbBtn.getLayoutParams();
if(event.getAction()==MotionEvent.ACTION_DOWN)
{
Log.d("ok","down");
mX = (int) event.getX() - imbBtn.getWidth() / 2;
mY = (int) event.getY() - imbBtn.getHeight() / 2;
et1.setText("mX down: "+String.valueOf(mX));
et2.setText("mY down: "+String.valueOf(mY));
}
else if (event.getAction()==MotionEvent.ACTION_UP)
{
Log.d("ok","up");
rlOut.addView(ivB, params);
p.leftMargin=4;
params.leftMargin = 60;
params.topMargin = 20;
rlOut.addView(imgP, p);
Log.d("ok","p");
}
else if (event.getAction()==MotionEvent.ACTION_MOVE)
{
Log.d("ok","move");
mX = (int) event.getX() - imbBtn.getWidth() / 2;
mY = (int) event.getY() - imbBtn.getHeight() / 2;
et1.setText("mX move: "+String.valueOf(mX));
et2.setText("mY move: "+String.valueOf(mY));
}
return false;
}
});
}
}
OnCreate method is the place where you set the setContentView(R.layout.main). I suppose the variable rlOut stands for RelativeLayout which might be in your main layout. Call the above function within the OnCreate methods after you set the contentView and have initialized the variable rlOut using findViewById. Or if the variable rlOut is in some other layout file then you will have to first inflate that layout using layout inflater and then find the view using findViewById method.
Hope this helps.
EDIT
The following code should probably be the solution you are looking for:
imbBtn.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
LayoutParams par = (LayoutParams)imbBtn.getLayoutParams();
if (event.getAction()==MotionEvent.ACTION_MOVE)
{
Log.d("ok","move");
mX = (int) event.getX() - imbBtn.getWidth() / 2;
mY = (int) event.getY() - imbBtn.getHeight() / 2;
par.leftMargin = imbBtn.getLeft() + mX;
par.topMargin = imbBtn.getTop() + mY;
imbBtn.setLayoutParams(par);
et1.setText("mX move: "+String.valueOf(mX));
et2.setText("mY move: "+String.valueOf(mY));
}
return false;
}
});
MotionEvent.ACTION_MOVE is the only event you need to capture. Hope this solution is helpful to you.

Error from starting a view from an activity

public class MAINActivity extends TabActivity {
host.addTab(host.newTabSpec("Settings")
.setIndicator("Settings", getResources().getDrawable(R.drawable.icon_user))
.setContent(new Intent(this, TwoDScrollView.class)));
........
}
public class TwoDScrollView extends Activity {
private RelativeLayout container;
private int currentX;
private int currentY;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.design);
container = (RelativeLayout)findViewById(R.id.container);
int top = 0;
int left = 0;
ImageView image1 = (ImageView)findViewById(R.id.imageView1);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(left, top, 0, 0);
container.addView(image1, layoutParams);
ImageView image2 = (ImageView)findViewById(R.id.imageView2);
left+= 100;
layoutParams.setMargins(left, top, 0, 0);
container.addView(image2, layoutParams);
ImageView image3 = (ImageView)findViewById(R.id.imageView3);
left= 0;
top+= 100;
layoutParams.setMargins(left, top, 0, 0);
container.addView(image3, layoutParams);
ImageView image4 = (ImageView)findViewById(R.id.imageView4);
left+= 100;
layoutParams.setMargins(left, top, 0, 0);
container.addView(image4, layoutParams);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
currentX = (int) event.getRawX();
currentY = (int) event.getRawY();
break;
}
case MotionEvent.ACTION_MOVE: {
int x2 = (int) event.getRawX();
int y2 = (int) event.getRawY();
container.scrollBy(currentX - x2 , currentY - y2);
currentX = x2;
currentY = y2;
break;
}
case MotionEvent.ACTION_UP: {
break;
}
}
return true;
}
}
When I trying to add the TwoDScrollView Class to the tabbars I got an error of IllegalStateException. The specified child already has a parent. You must removeView() on the child's parent first. What does all those means?
What's happening is that you are implicitly inflating your layout by calling setContentView which creates a bunch of views including four ImageViews apparently in a RelativeLayout. Then you're doing findViewById to find these ImageViews and the RelativeLayout, and after changing their margins programmatically, you add them back to the same layout which already contained them. This is why you get an exception. Those ImageViews already have a parent (the RelativeLayout) and you're trying to give them a new parent (even if it is that same RelativeLayout) without first removing them from their parent. You don't need to call addView at all in this case.

Categories

Resources