Android - горизонтальная прокрутка нескольких видимых элементов
EDIT: см. мой собственный ответ для простого решения
ВАЖНО: Bounty предлагается для четкого способа изменения ViewPager, чтобы удовлетворить описанный ниже сценарий. Пожалуйста, не предлагайте HorizontalScrollView - мне нужен полный сценарий жизненного цикла фрагмента
Мне нужно реализовать горизонтальную прокрутку видов Fragments
, в которых один элемент находится в центре, а элементы справа/слева частично или полностью видимы. ViewPager
плохо подходит для задачи, поскольку он сфокусирован на отображении одного элемента в каждый момент времени.
Чтобы было легче понять ниже, это быстрый эскиз, в котором элементы 1, 5 и 6 находятся за пределами видимой области. И и хотите, чтобы этот отображаемый номер был настроен так, например, в портретном режиме, я покажу только 2 (или, возможно, только один) элемент.
Я не пытаюсь приспособить 3 элемента на экране, пока показан центральный элемент, другие могут быть обрезаны. На маленьком экране ОК, чтобы иметь 1 центральный элемент, и по мере того, как размер экрана увеличивается в несколько раз (обрезано в порядке), элементы должны отображаться
Я понимаю, что это похоже на галерею, но снова элементы - это не простые изображения, а Fragments
с вертикально прокручиваемым списком в каждом фрагменте
P.S. Найденный blogpost от @Commonsware, что содержит 3 разных подхода. Для моей потребности мне нравится # 3
![enter image description here]()
Ответы
Ответ 1
У этого есть удивительно легкий ответ, я даже не уверен, почему он не был опубликован сразу. Все, что мне нужно было сделать, чтобы получить точный эффект, было переопределить метод PagerAdapter#getPageWidth
. По умолчанию он возвращает 1, но если вы установите его на 0,5, вы получите 2 страницы, 0,33 даст вам 3 и т.д. В зависимости от ширины разделителя между элементами пейджера вам может потребоваться немного уменьшить значение.
См. следующий фрагмент:
@Override
public float getPageWidth(final int position) {
// this will have 3 pages in a single view
return 0.32f;
}
Ответ 2
Как только я написал что-то похожее на шаблон. В моем примере я могу прокручивать кнопки вверх и вниз и боком. Вы можете немного изменить его, чтобы выполнить ваши требования. В моем примере у меня есть 4 вида, расположенных следующим образом:
1 2
3 4
Похоже на это. На картинке прокручиваюсь из вида 1 вправо, чтобы посмотреть 2:
![Android View Scrolling]()
Код состоит из этого 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>
и этот код Java:
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;
// }
// });
}
}
Большие числа на каждом экране - это черные фоновые изображения с теми цифрами, которые на нем нарисованы. (Я не публиковал его здесь, потому что вы, вероятно, измените код).
Ответ 3
Мы делаем что-то очень похожее, как вы описываете, используя Gallery
с Fragments
, и адаптер галереи, расширяющий BaseAdapter
. Я бы рекомендовал пойти с галереей для достижения вашей цели (мы также используем ViewPager
для представления, где нам не нужно видеть другие фрагменты).
Ответ 4
Я могу думать о двух способах реализации этого.
-
По ViewSwitcher.
Вот отличный видеоролик , показывающий, как он работает с onGestureListener. Тем не менее, я не уверен, будет ли это работать с несколькими видами, например, на ваших изображениях.
-
В качестве альтернативы вы можете использовать HorizontalScrollView.
Однако это часто вызывает проблемы, если у вас есть один ScrollView внутри другого, но это может стоить!
Сообщите мне, как это происходит,
Удачи!
Ответ 5
В дополнение к второму ответу MrZander посмотрите на fooobar.com/questions/14365/...
Ответ 6
Просмотрите этот пост в блоге о том, как написать пользовательский горизонтальный прокрутка, чтобы достичь чего-то подобного. В этом примере отображается только один экран, но вы можете легко изменить его для своих нужд.
Ответ 7
Если вы хотите расширить ViewPager, просто переопределите метод draw и setOffscreenPageLimit (int limit). Но я рекомендую использовать FragmentPageAdapter
, если ваши фрагменты сами по себе являются сложными.
Вы можете проверить исходный код здесь, или если вы хотите проверить его в пакете поддержки, вы можете сделайте это здесь.