Подскажите, как сделать игровое поле шире экрана устройства? Чтобы можно было сдвигать, например комнату, видеть и взаимодействовать с объектами (мебелью), находящимися вне экрана, но выдвигаемых с комнатой на экран. Перелистывание страниц не подходит, хочется чтобы картинка комнаты была целой.
Можете использовать HorizontalScrollView
<HorizontalScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:scaleType="center"
android:src="@drawable/room" />
</HorizontalScrollView>
Попробуйте такой FrameLayout
, куда поместите всё, что надо. В своё время успешно использовал его для игры с большим зумящимся полем. ScaleGestureDetector
добавлял для того, чтобы поле корректно отлавливало onTouch
, onClick
и onLongClick
public class ZoomLayout extends FrameLayout implements ScaleGestureDetector.OnScaleGestureListener {
private enum Mode {
NONE,
DRAG,
ZOOM
}
public static boolean DRAGGING =false;
private static final float MIN_ZOOM = 1.0f;
private static final float MAX_ZOOM = 4.0f;
private Mode mode = Mode.NONE;
private float scale = 1.0f;
private float lastScaleFactor = 0f;
// Where the finger first touches the screen
private float startX = 0f;
private float startY = 0f;
// How much to translate the canvas
private float dx = 0f;
private float dy = 0f;
private float prevDx = 0f;
private float prevDy = 0f;
ScaleGestureDetector scaleDetector;
public ZoomLayout(Context context) {
super(context);
init(context);
}
public ZoomLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public ZoomLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean upper = super.onInterceptTouchEvent(ev);
DRAGGING = false;
if (!upper) {
switch (ev.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
if (scale > MIN_ZOOM) {
mode = Mode.DRAG;
startX = ev.getX() - prevDx;
startY = ev.getY() - prevDy;
}
break;
case MotionEvent.ACTION_MOVE:
DRAGGING = true;
if (mode == Mode.DRAG) {
dx = ev.getX() - startX;
dy = ev.getY() - startY;
}
break;
case MotionEvent.ACTION_POINTER_DOWN:
mode = Mode.ZOOM;
break;
case MotionEvent.ACTION_POINTER_UP:
mode = Mode.DRAG;
break;
case MotionEvent.ACTION_UP:
mode = Mode.NONE;
prevDx = dx;
prevDy = dy;
break;
}
scaleDetector.onTouchEvent(ev);
if ((mode == Mode.DRAG && scale >= MIN_ZOOM) || mode == Mode.ZOOM) {
rescale();
}
}
return upper;
}
private void init(Context context) {
scaleDetector = new ScaleGestureDetector(context, this);
this.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return true;
}
});
}
public void setScale(float scale) {
this.scale = scale;
}
public void rescale() {
for (int i = 0; i < getChildCount(); i++) {
getParent().requestDisallowInterceptTouchEvent(true);
float maxDx = (child(i).getWidth() - (child(i).getWidth() / scale)) / 2 * scale;
float maxDy = (child(i).getHeight() - (child(i).getHeight() / scale)) / 2 * scale;
dx = Math.min(Math.max(dx, -maxDx), maxDx);
dy = Math.min(Math.max(dy, -maxDy), maxDy);
applyScaleAndTranslation(i);
}
}
@Override
public boolean onScaleBegin(ScaleGestureDetector scaleDetector) {
return true;
}
@Override
public boolean onScale(ScaleGestureDetector scaleDetector) {
float scaleFactor = scaleDetector.getScaleFactor();
if (lastScaleFactor == 0 || (Math.signum(scaleFactor) == Math.signum(lastScaleFactor))) {
scale *= scaleFactor;
scale = Math.max(MIN_ZOOM, Math.min(scale, MAX_ZOOM));
lastScaleFactor = scaleFactor;
} else {
lastScaleFactor = 0;
}
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector scaleDetector) {
}
private void applyScaleAndTranslation(int i) {
child(i).setScaleX(scale);
child(i).setScaleY(scale);
child(i).setTranslationX(dx);
child(i).setTranslationY(dy);
}
private View child(int i) {
return getChildAt(i);
}
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
В моем тестовом приложении настроена аутентификация через фильтрыПри первом запуске программы, нужно вводить дважды логин и пароль, потому...
В моем приложении используется Firebase databse и имеет следующую структуру: