Sliding screens inside the application
Hello!
Modern mobile devices are primarily focused on finger control, in particular gestures and touches. This feature adds certain specificity to the organization of user interfaces. Intuitive solutions that require the least effort from the user and at the same time unobtrusive, preserving the maximum usable space, go to the main role. non cluttering user interface.
An example of such solutions is switching between the working screens in Android, where to move from one screen to another it is enough to perform a gesture to the right or left. The possible implementation of such a solution will be discussed in this post.
Instead of joining
In order to illustrate what will be discussed later, and thereby add clarity, I recorded a short video of the application, which I will do today:
In the application shown above, there are four unrelated View , the movement between which is carried out by gestures to the right / left on the screen. The content of the View could be arbitrary, but for simplicity of perception, I made them colorful and numbered.
Such functionality is not basic, i.e. does not have a ready-made embedded solution. And also, oddly enough, it is not very common, and, probably, because of this, it is not adequately covered on the Internet.
Development
To implement the above application, you must perform the following steps:
- Find or implement a container for convenient storage and movement between View
- Intercept user gestures and, based on the information received, make a conclusion in which direction to “move” view
- Add animation to visualize movements between screens
Now create four views between which we will move, in my example they have the form:
Next, you need to link the existing view with ViewFlipper. To do this, add the following code in the OnCreate method of the base Activity :
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Устанавливаем listener касаний, для последующего перехвата жестов
LinearLayout mainLayout = (LinearLayout) findViewById(R.id.main_layout);
mainLayout.setOnTouchListener(this);
// Получаем объект ViewFlipper
flipper = (ViewFlipper) findViewById(R.id.flipper);
// Создаем View и добавляем их в уже готовый flipper
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
int layouts[] = new int[]{ R.layout.first, R.layout.second, R.layout.third, R.layout.fourth };
for (int layout : layouts)
flipper.addView(inflater.inflate(layout, null));
}
Now we can move between view calls to the showNext () and showPrevious () methods of the flipper object .
User gestures raise OnTouch events ; to process these events, you must implement the method:
boolean onTouch(View view, MotionEvent event)
In this method, in the object of the MotionEvent class , there is all the necessary information and a gesture made.
Because if we need to understand where the gesture was made to the right or left, then we will do it very simply: we will save the coordinate on the X axis when we click on the screen, and compare it with the coordinate after the screen is released. If the initial value is greater, then this is a movement to the left, otherwise to the right. The code looks simple enough:
public boolean onTouch(View view, MotionEvent event)
{
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN: // Пользователь нажал на экран, т.е. начало движения
// fromPosition - координата по оси X начала выполнения операции
fromPosition = event.getX();
break;
case MotionEvent.ACTION_UP: // Пользователь отпустил экран, т.е. окончание движения
float toPosition = event.getX();
if (fromPosition > toPosition)
flipper.showNext();
else if (fromPosition < toPosition)
flipper.showPrevious();
default:
break;
}
return true;
}
It remains to add animation. ViewFlipper like all heirs ViewAnimator supports methods: setInAnimation (...) and setOutAnimation (...) , through which you can set the animation ( the Animation ) view entry into the screen and disappears from the screen view. But since Since our animation will differ depending on the gestures, you will have to specify it again each time, based on the current operation. Those. The onTouch method needs to be modified as follows:
...
if (fromPosition > toPosition)
{
flipper.setInAnimation(AnimationUtils.loadAnimation(this,R.anim.go_next_in));
flipper.setOutAnimation(AnimationUtils.loadAnimation(this,R.anim.go_next_out));
flipper.showNext();
}
else if (fromPosition < toPosition)
{
flipper.setInAnimation(AnimationUtils.loadAnimation(this,R.anim.go_prev_in));
flipper.setOutAnimation(AnimationUtils.loadAnimation(this,R.anim.go_prev_out));
flipper.showPrevious();
}
...
Where R.anim. * Resources with animation of appearance and disappearance view. I will not give all four options, I will give only the first one (all the rest can be seen in the example project that I will attach to the post):
All is ready! You can download the project with an example from here .
UPD ViewFlipper option without releasing a finger (changing the onTouch method):
...
// Вместо ACTION_UP
case MotionEvent.ACTION_MOVE:
float toPosition = event.getX();
// MOVE_LENGTH - расстояние по оси X, после которого можно переходить на след. экран
// В моем тестовом примере MOVE_LENGTH = 150
if ((fromPosition - MOVE_LENGTH) > toPosition)
{
fromPosition = toPosition;
flipper.setInAnimation(AnimationUtils.loadAnimation(this,R.anim.go_next_in));
flipper.setOutAnimation(AnimationUtils.loadAnimation(this,R.anim.go_next_out));
flipper.showNext();
}
else if ((fromPosition + MOVE_LENGTH) < toPosition)
{
fromPosition = toPosition;
flipper.setInAnimation(AnimationUtils.loadAnimation(this,R.anim.go_prev_in));
flipper.setOutAnimation(AnimationUtils.loadAnimation(this,R.anim.go_prev_out));
flipper.showPrevious();
}
...
UPD 2. If you prefer a slide with a preview of the next page, then you can look at solutions without ViewFlipper, based on ViewGroup and scrollTo , an example can be found, for example, here .
Conclusion
The main advantage of sliding, when used correctly: unloading the user interface from redundant controls. As you can see, the implementation turned out to be simple, and the use of such functionality is truly wide.
But a fly in the ointment is still present. Firstly, if you look at my example for the first time, it’s almost impossible to guess that sliding is present there (this is an example and I didn’t set such a task here), and therefore the use of sliding requires other UI solutions explaining this sliding, for example, on the same Android home screens there is a “slider indicator” showing which screen the user is currently on. Secondly, if there are controls on the view that have their own reaction to pressing, scrolling, etc., the call to the onTouch method inside the ViewFlipper will be blocked by its earlier interception inside the child view, so you will have to additionally worry about throwing this event “ Top "to ViewFlipper.