i'm designing a automation for android by UiAutomatorTestCase class.
I want to control SeekBar swiping and TestView on UIAutomator.
for instance, if SeekBar is moved to left. TextView is changed negative number. so if the number is "40". I want to stop the swiping.
I could swipe the seekbar to left direction but can't stop it.
UiScrollable seekbar = new UiScrollable(new UiSelector().resourceId("com.test:id/setting_item_child_menu_seekbar"));
seekbar.swipeLeft(200);
please help me how can I stop that SeekBar when some test of TextView is "40".
I found alternative way to control seekbar, since I also found the standard methods hard to use because of some problems, so here it is:
private void clickSeekbar (float position) {
while ((seekBarUiObj2 = mDevice.findObject(By.res(BASIC_SAMPLE_PACKAGE+":id/seekbar"))) == null) {
mDevice.click(200,200);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Rect rect = seekBarUiObj2.getVisibleBounds();
mDevice.click(rect.left+5/*pixels*/+(int)((rect.right-rect.left-10/*pixels*/)*position), ((rect.top+rect.bottom)/2));
}
The trick is to click on the device on the desired location on the seekbar.
It works.
The whlle loop makes sure the seekbar is on screen, if not tap the screen on some location, which makes seekbar to appear.
Then calculate the location to be clicked according to desired position.
Only if your seekbar is very thin like 1 or 2 pixels it might not work.
Related
I try to achieve the same behaviour of a floating label text as the TextInputLayout class already does but for a different purpose
I got everything working except the x translation of the textview. I don't know how to shift the correct amount of pixels.
It moves up correctly and shrinks down correctly but does not move straigh up because the center for scale is in the middle of the text view. But I want the text view do move straigh up. So my intention was to calculate the length of the text also scale this with the scale value and divide this by 2 (left and right). This does not work. Any ideas how to achieve this no matter the text length?
private void triggerAnimation(boolean fadeOut) {
if (fadeOut) {
float xTranslation = b.tvHint.getPaint().measureText(tvHint.getHint().toString())*0.6f/2;
tvHint.animate().translationY(-tvHint.getHeight() * 0.28f).translationXBy(-xTranslation).scaleX(0.6f).scaleY(0.6f);
} else {
tvHint.animate().translationY(0).translationX(0).scaleX(1f).scaleY(1f);
}
}
Okay it turns out that it is possible to change the coordinates pivot point so this will exactly reproduce the floating label
private void triggerAnimation(boolean fadeOut) {
if (fadeOut) {
tvHint.setPivotX(0);
tvHint.animate().translationY(-tvHint.getHeight() * 0.32f).scaleX(0.7f).scaleY(0.7f);
} else {
tvHint.animate().translationY(0).scaleX(1f).scaleY(1f);
}
}
I am trying to animate a pointer around the screen in an android application.
I am using an imageview as the pointer inside a relative layout as follows:
final RelativeLayout container = (RelativeLayout) findViewById(R.id.container);
pointer = (ImageView) findViewById(R.id.pointer);
pointer.animate().setDuration(2000);
I then want to move the pointer up 10 pixels every time I click a button:
// ONCLICK LISTENER FOR LEFT BUTTON
btnUp.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
//get positon of pointer
leftPoint = pointer.getLeft();
topPoint = pointer.getTop();
int xValue = container.getWidth() - pointer.getWidth();
int yValue = container.getHeight() - pointer.getHeight();
pointer.animate().x(leftPoint).y(topPoint-10);
}
});
This works the first time I click the button but will not move it any subsequent times. I have tried making the int points static but this did not help.
Any help greatly appreciated.
This might sound counter-intuitive, but animating a view doesn't change its location. Your code is demonstrating it. When you do this line:
topPoint = pointer.getTop();
You get the same value every time.
You need to change pointer's position at the end of the animation.
This answer shows how someone else has done it.
Other Considerations
You could use object animator, if you are only targeting SDK 11 and above. Here is a little intro to it.
If you want to interrupt your animation, you can check its status, and find out its current y offset. You can add that to the position of the view before starting the animation. Here is an example.
As I've a master in MS Paint, I will just upload a picture selfdescripting what I'm trying to achieve.
I've searched, but I'm not really sure what do I've to search. I've found something called Animations. I managed to rotate, fade, etc an element from a View (with this great tutorial http://www.vogella.com/articles/AndroidAnimation/article.html)
But this is a bit limited for what I'm trying to achieve, and now, I'm stuck, because I don't know how is this really called in android development. Tried words like "scrollup layouts" but I didn't get any better results.
Can you give me some tips?
Thank you.
You can see a live example, with this app: https://play.google.com/store/apps/details?id=alexcrusher.just6weeks
Sincerely,
Sergi
Use something like this as your layout (Use Linear, Relative or other layout if you wish):
<LinearLayout
android:id="#+id/lty_parent">
<LinearLayout
android:id="#+id/lyt_first" />
<LinearLayout
android:id="#+id/lyt_second"/>
</LinearLayout>
And then in an onClick method on whatever you want to use to control it, set the Visibility between Visible and Gone.
public void buttonClickListener(){
((Button) findViewById(R.id.your_button))
.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (lyt_second.getVisibility() == View.GONE) {
lyt_second.setVisibility(View.VISIBILE);
}
else {
lyt_second.setVisibility(View.GONE);
}
});
Which is fine if you just want a simple appear/disappear with nothing fancy. Things get a little bit more complicated if you want to animate it, as you need to play around with negative margins in order to make it appear to grow and shrink, like so:
We use the same onClick method that we did before, but this time when we click it starts up a custom SlideAnimation for the hidden/visible view.
#Override
public void onClick(View v) {
SlideAnimation slideAnim = new SlideAnimation(lyt_second, time);
lyt_second.startAnimation(slideAnim);
}
The implementation of the SlideAnimation is based on a general Animation class, which we extend and then Override the transformation.
public SlideAnimation(View view, int duration) {
//Set the duration of the animation to the int we passed in
setDuration(duration);
//Set the view to be animated to the view we passed in
viewToBeAnimated = view;
//Get the Margin Parameters for the view so we can edit them
viewMarginParams = (MarginLayoutParams) view.getLayoutParams();
//If the view is VISIBLE, hide it after. If it's GONE, show it before we start.
hideAfter = (view.getVisibility() == View.VISIBLE);
//First off, start the margin at the bottom margin we've already set.
//You need your layout to have a negative margin for this to work correctly.
marginStart = viewMarginParams.bottomMargin;
//Decide if we're expanding or collapsing
if (marginStart == 0){
marginEnd = 0 - view.getHeight();
}
else {
marginEnd = 0;
}
//Make sure the view is visible for our animation
view.setVisibility(View.VISIBLE);
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
super.applyTransformation(interpolatedTime, t);
if (interpolatedTime < 1.0f) {
// Setting the new bottom margin to the start of the margin
// plus the inbetween bits
viewMarginParams.bottomMargin = marginStart
+ (int) ((marginEnd - marginStart) * interpolatedTime);
// Request the layout as it happens so we can see it redrawing
viewToBeAnimated.requestLayout();
// Make sure we have finished before we mess about with the rest of it
} else if (!alreadyFinished) {
viewMarginParams.bottomMargin = marginEnd;
viewToBeAnimated.requestLayout();
if (hideAfter) {
viewToBeAnimated.setVisibility(View.GONE);
}
alreadyFinished = true;
}
hideAfter = false;
}
}
EDIT: If anyone had used this code before and found that if you click on the button that starts the animation more than once before the animation was finished, it would mess up the animation from then on, causing it to always hide the view after the animation finished. I missed the reset of the hideAfter boolean near the bottom of the code, added it now.
you can do this manually by using setvisibility feature on the event onClick()
or
use this
dynamically adding two views one below other
i have Horizontal scrollview with 50 controll,as i am scroll it will display 50 gracefully.but at initially user not able to understand that this is scrollview and "I need to scroll for next item". so i have simply put two image at Right side and left side as you can see in image.now my problem is "i don't able to understand that how can i invisible left side arrow to visible & invisible right side arrow".
Edit I just realized how old this post is, but maybe it will help someone in the future.
Alright this is my first post so hopefully I can format it correctly. I actually had this exact same problem so I'll post my solution for it. I used images for the arrows.
hsv = (HorizontalScrollView) findViewById(R.id.HorizontalScrollView);
left_arrow = (ImageView) findViewById(R.id.left_arrow);
right_arrow = (ImageView) findViewById(R.id.right_arrow);
hsv.getViewTreeObserver().addOnScrollChangedListener(new OnScrollChangedListener() {
#Override
public void onScrollChanged() {
// TODO Auto-generated method stub
//Checks if your horizontalscrollview can scroll left
if (!hsv.canScrollHorizontally(-1))
{
left_arrow.setVisibility(View.INVISIBLE);
}
else
{
left_arrow.setVisibility(View.VISIBLE);
}
//Checks if the horizontalscrollview can scroll right
if(!hsv.canScrollHorizontally(1))
{
right_arrow.setVisibility(View.INVISIBLE);
}
else
{
right_arrow.setVisibility(View.VISIBLE);
}
}
});
I put this in my onCreate method and it works like a charm. The listener checks when you scroll and the canScrollHorizontally uses a postive / negative integer to determine if the view can scroll any more. Positive for right, negative for left.
I attempted to use a SeekBar for the first time, and I was disappointed with the results. I have an app that needs to use a slider to cover 80 spots. I want the user to be able to move in .5 increments (i.e. 10.5, 11.0). My max range is 40, which is why I doubled it to 80 to account for the decimals.
Everything worked, but when I put it on my Droid, the performance was terrible in my opinion. When trying to stop on 21.5, the slider usually stopped at 22.0 or 22.5, and I had to take extra time to try and inch it over. Other times I would try to select the slider and it was unresponsive. I'm not as concerned about the unresponsiveness, but I can not put the SeekBar in my app if it requires the user to have exact precision to hit a certain spot.
Is there anything that I can do to adjust the SeekBar so that it is easy to hit the number you are trying to land on without difficulty? I'm not sure if the problem is occurring because my SeekBar contains a large amount of possible values, and with screen size limited this forces the numbers to be smashed closer together? Or if this is just the way it behaves in general.
If there isn't a good way to adjust the sensitivity, is there a good alternative that I can use that provides similar functionality?
I have the exact same problem and came up with my own way of reducing the sensitivity. The problem for me happens when I am leaving the slider and it unintentionally gets repositioned, because of thickness of fingers etc. So I wrote a timer to see if the position was selected for a while and snap to this position while leaving the seekbar. This method is a bit clumsy but this is the best I can think of, given I do not want +/- buttons as suggested above. It works well for my needs. Here is the code for anyone interested:
seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
int lastProgress = 0;
Timer endTimer = null;
boolean timerExpired = false;
class SeekBarTimerTask extends TimerTask {
public void run() {
timerExpired = true;
}
}
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if(timerExpired == false) {
// clean up the previous timer and start a new one
setTimer();
}
else {
// if the timer has expired, do not honor small variations of 2%
if(Math.abs(progress - lastProgress) <= seekBar.getMax() * 0.02) {
seekBar.setProgress(lastProgress);
return;
}
else {
// The variation is not small. This means that the seekbar position change
// was intentional. Honor it and schedule the timer again.
setTimer();
}
}
lastProgress = progress;
}
public void onStartTrackingTouch (SeekBar seekBar) {}
public void onStopTrackingTouch (SeekBar seekBar) {
timerExpired = false;
endTimer.cancel();
endTimer.purge();
}
private void setTimer() {
if(endTimer != null) {
endTimer.cancel();
endTimer.purge();
}
timerExpired = false;
endTimer = new Timer();
endTimer.schedule(new SeekBarTimerTask(), 300);
}
});
I'm not sure if the problem is
occurring because my SeekBar contains
a large amount of possible values, and
with screen size limited this forces
the numbers to be smashed closer
together?
Pretty much this. One thing you could do is add a small plus and minus button beside the seekbar, which increment and decrement the value by 0.5. This way you could still use the seekbar for general cases, and refine your selection with the buttons if needed. Maybe not the most elegant solution, but it would certainly work.