Android - horizontal scrolling of several visible elements

EDIT: see my own answer for a simple solution

IMPORTANT : Bounty is proposed for a clear way to modify the ViewPager to suit the scenario described below. Please do not offer HorizontalScrollView - I need a full fragment lifecycle script

I need to implement horizontal scrolling of Fragments views in which one element is in the center and the elements on the right / left are partially or fully visible. ViewPager poorly suited for the task, because it focuses on displaying one item at a time.

To make it easier to understand below, this is a quick sketch in which elements 1, 5, and 6 are outside the visible area. And you want this displayed number to be configured like this, for example, in portrait mode, I will show only 2 (or, possibly, only one) element.

I am not trying to fit 3 elements on the screen while the central element is shown, others may be cropped. On a small screen, OK, in order to have 1 central element, and as the screen size increases several times (cropped in order), the elements should be displayed

I understand that this looks like a gallery, but again the elements are not simple images, but Fragments with a vertically scrolling list in each fragment

PS Found a blogpost from @Commonsware that contains 3 different approaches . For my need, I like # 3

enter image description here

+47
android android-viewpager horizontal-scrolling
Oct 08 '11 at 4:22
source share
7 answers

This one has a surprisingly easy answer, I'm not even sure why it was not published right away. All I had to do to get the exact effect was to override the PagerAdapter#getPageWidth . By default, it returns 1, but if you set it to 0.5, you will get 2 pages, 0.33 will give you 3, etc. Depending on the width of the separator between the pager elements, you may need to slightly decrease the value.

See the following snippet:

  @Override public float getPageWidth(final int position) { // this will have 3 pages in a single view return 0.32f; } 
+24
Nov 24 '12 at 1:32
source share

As soon as I wrote something similar to the template. In my example, I can scroll the buttons up and down and sideways. You can change it a little to fulfill your requirements. In my example, I have 4 views arranged as follows:

12
3 4

It looks like this. In the picture, I scroll from view 1 to the right to see 2:

Android View Scrolling

The code consists of this xml:

 <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <LinearLayout android:layout_height="350sp" android:layout_width="320sp"> <LinearLayout android:id="@+id/viewContainer" android:background="#CCCCCC" android:layout_width="640sp" android:layout_height="700sp"> </LinearLayout> </LinearLayout> <TableLayout android:id="@+id/tableLayout" android:layout_width="320sp" android:layout_height="fill_parent" android:stretchColumns="1" android:gravity="bottom" android:layout_alignParentBottom="true"> <TableRow android:background="#333333" android:gravity="bottom"> <Button android:id="@+id/btnUp" android:layout_width="60sp" android:layout_height="50sp" android:text="Lift U" /> <Button android:layout_width="60sp" android:layout_height="50sp" android:visibility="invisible" /> <Button android:layout_width="60sp" android:layout_height="50sp" android:visibility="invisible" /> <Button android:id="@+id/btnScreenUp" android:layout_width="60sp" android:layout_height="50sp" android:layout_gravity="right" android:text="Scrn U" /> </TableRow> <TableRow android:background="#444444" android:layout_gravity="right"> <Button android:id="@+id/btnDown" android:layout_width="60sp" android:layout_height="50sp" android:text="Lift D" /> <Button android:id="@+id/btnEnter" android:layout_width="60sp" android:layout_height="50sp" android:text="Enter" /> <Button android:id="@+id/btnScreenLeft" android:layout_width="60sp" android:layout_height="50sp" android:layout_gravity="right" android:text="Scrn L" /> <Button android:id="@+id/btnScreenDown" android:layout_width="60sp" android:layout_height="50sp" android:layout_gravity="right" android:text="Scrn D" /> <Button android:id="@+id/btnScreenRight" android:layout_width="60sp" android:layout_height="50sp" android:layout_gravity="right" android:text="Scrn R" /> </TableRow> </TableLayout> </FrameLayout> 

and this java code:

 import android.app.Activity; import android.os.Bundle; import android.util.DisplayMetrics; import android.view.Gravity; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.widget.Button; import android.widget.LinearLayout; import android.widget.TextView; public class ViewSwitcherTest extends Activity { private TextView view1, view2, view3, view4; private Button btnUp, btnEnter, btnDown, btnScreenDown, btnScreenUp, btnScreenLeft, btnScreenRight; private LinearLayout viewContainer; // private TableLayout tableLayout; private LinearLayout.LayoutParams layoutParams; private DisplayMetrics metrics = new DisplayMetrics(); private int top = 0, left = 0; private float density = 1.0f; // private ViewSwitcher switcher; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindowManager().getDefaultDisplay().getMetrics(metrics); density = metrics.density; setContentView(R.layout.main); // Buttons btnEnter = (Button)findViewById(R.id.btnEnter); btnUp = (Button)findViewById(R.id.btnUp); btnDown = (Button)findViewById(R.id.btnDown); btnScreenDown = (Button)findViewById(R.id.btnScreenDown); btnScreenUp = (Button)findViewById(R.id.btnScreenUp); btnScreenLeft = (Button)findViewById(R.id.btnScreenLeft); btnScreenRight = (Button)findViewById(R.id.btnScreenRight); // -------- // tableLayout = (TableLayout)findViewById(R.id.tableLayout); view1 = new TextView(this); view1.setBackgroundResource(R.drawable.view1); view1.setHeight((int)(350*density)); view1.setWidth((int)(320*density)); view1.setGravity(Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL); layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); layoutParams.setMargins(left, top, 0, 0); viewContainer = (LinearLayout)findViewById(R.id.viewContainer); viewContainer.addView(view1, layoutParams); //Add 2nd view view2 = new TextView(this); view2.setBackgroundResource(R.drawable.view2); view2.setHeight((int)(350*density)); view2.setWidth((int)(320*density)); view2.setGravity(Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL); layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); layoutParams.setMargins(left, top, 0, 0); viewContainer.addView(view2, layoutParams); //Add 3rd view view3 = new TextView(this); view3.setBackgroundResource(R.drawable.view3); view3.setHeight((int)(350*density)); view3.setWidth((int)(320*density)); view3.setGravity(Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL); top += 350*density; left += 640*density*(-1); layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); layoutParams.setMargins(left, top, 0, 0); viewContainer.addView(view3, layoutParams); //add 4th view view4 = new TextView(this); view4.setBackgroundResource(R.drawable.view4); view4.setHeight((int)(350*density)); view4.setWidth((int)(320*density)); view4.setGravity(Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL); top += 0; left += 640*density; layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); layoutParams.setMargins(left, top, 0, 0); viewContainer.addView(view4, layoutParams); btnEnter.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // Quit the application for now finish(); } }); btnScreenLeft.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { viewContainer.scrollBy(-10,0); } }); btnScreenRight.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { viewContainer.scrollBy(10,0); } }); btnScreenUp.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { viewContainer.scrollBy(0,-10); } }); btnScreenDown.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { viewContainer.scrollBy(0,10); } }); // view1.setOnKeyListener(new OnKeyListener() { // @Override // public boolean onKey(View v, int keyCode, KeyEvent event) { // if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) // viewContainer.scrollBy(0,10); // return true; // } // }); } } 

The large numbers on each screen are black background images with the numbers that are drawn on it. (I did not publish it here because you are likely to change the code).

+2
Dec 28 '11 at 18:57
source share

We are doing something very similar as you describe, using Gallery with Fragments , and a gallery adapter that extends BaseAdapter . I would recommend going with the gallery to achieve your goal (we also use the ViewPager to represent where we don’t need to see other fragments).

+1
Apr 19 '12 at 17:48
source share

I can think of two ways to implement this.

  • By ViewSwitcher . Here's a great video showing how it works with onGestureListener . However, I'm not sure if this will work with multiple views, for example, in your images.

  • Alternatively, you can use HorizontalScrollView . However, this often causes problems if you have one ScrollView inside another, but it can be worth it!

Let me know how this happens, good luck!

0
Dec 08 2018-11-12T00: 00Z
source share

In addition to MrZander's second answer, take a look at https://stackoverflow.com/a/3169/

0
Dec 28 2018-11-12T00:
source share

Check out this blog post on how to write custom horizontal scrolling to achieve something similar. This example displays only one screen, but you can easily change it for your needs.

0
Dec 28 '11 at 15:58
source share

If you want to extend the ViewPager, just override the draw method and setOffscreenPageLimit (int limit). But I recommend using the FragmentPageAdapter if your fragments themselves are complex.

You can check the source code here , or if you want to check it in the support package, you can do it here .

0
Dec 29 2018-11-12T00:
source share



All Articles