В настоящее время я разрабатываю картографическое приложение для проекта и хочу, чтобы моя карта представляла собой большое изображение. (Нет, использование уже созданной реализации MapView для этого проекта невозможно)
Для этого мне нужно было иметь возможность перетаскивать изображение по экрану, вращать его, увеличивать масштаб с помощью щипка и дважды касаться экрана, чтобы увеличить масштаб. и вышло.
Я пробовал реализовать все это сам, но, кроме перетаскивания изображения на экран, успех был минимальным. результаты с ошибками и прерывистыми.
Поэтому я отказался от использования библиотеки и выбрал представление изображения в масштабе субдискретизации, потому что она также имеет субдискретизацию. Но в нем еще не реализован жест вращения, поэтому мне пришлось добавить его самому. Я использовал этот ответ в качестве руководства, но столкнулся с проблемой. Хотя изображение визуально вращалось, вращалось не изображение, а вид. Это приводит к тому, что само изображение при перемещении с использованием библиотеки обрезается из вида, если оно повернуто.
(представьте, что изображение находится под углом и при перемещении перпендикулярно тому месту, куда оно обращено, оно исчезает на пороге представление)
Я попробовал увеличить размер представления так, чтобы его ширина и высота были равны (высоте экрана).
Я ожидал, что так и будет, когда оно будет при повороте весь вид по-прежнему оставался бы на экране, устраняя точку отсечения, но это приводило к двум вещам. Теперь загрузка изображения занимает намного больше времени, что является проблемой, если я буду использовать огромную карту в будущем, и когда оно загружается, оно загружается в супер «увеличенном масштабе» (на самом деле оно не увеличено, это просто так кажется). потому что он пытается заполнить все представление).
XML
Код активности
public class MapActivity extends BaseActivity implements RotationGestureDetector.OnRotationGestureListener, View.OnTouchListener {
BottomNavigationView navbar;
SubsamplingScaleImageView mapImage;
private RotationGestureDetector mRotationDetector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_map);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
init();
navbar.setOnItemSelectedListener(this::onOptionsItemSelected);
}
public void init(){
navbar=findViewById(R.id.bottom_navbar1);
mapImage = findViewById(R.id.map);
mapImage.setOnTouchListener(this);
mRotationDetector = new RotationGestureDetector(this);
mapImage.setImage(ImageSource.resource(R.drawable.checkerboard));
mapImage.setPanLimit(SubsamplingScaleImageView.PAN_LIMIT_OUTSIDE);
}
@Override
public void OnRotation(RotationGestureDetector rotationDetector) {
float angle = rotationDetector.getAngle();
mapImage.setRotation(mapImage.getRotation() + (-angle));
}
@Override
public boolean onTouch(View v, MotionEvent event) {
mRotationDetector.onTouchEvent(event);
return false;
}
}
(Базовая активность просто обрабатывает меню)
Класс (взято из упомянутого ответа)
public class RotationGestureDetector{
private static final int INVALID_POINTER_ID = -1;
private float fX, fY, sX, sY;
private int ptrID1, ptrID2;
private float mAngle;
private OnRotationGestureListener mListener;
public float getAngle() {
return mAngle;
}
public RotationGestureDetector(OnRotationGestureListener listener){
mListener = listener;
ptrID1 = INVALID_POINTER_ID;
ptrID2 = INVALID_POINTER_ID;
}
public boolean onTouchEvent(MotionEvent event){
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
ptrID1 = event.getPointerId(event.getActionIndex());
break;
case MotionEvent.ACTION_POINTER_DOWN:
ptrID2 = event.getPointerId(event.getActionIndex());
sX = event.getX(event.findPointerIndex(ptrID1));
sY = event.getY(event.findPointerIndex(ptrID1));
fX = event.getX(event.findPointerIndex(ptrID2));
fY = event.getY(event.findPointerIndex(ptrID2));
break;
case MotionEvent.ACTION_MOVE:
if(ptrID1 != INVALID_POINTER_ID && ptrID2 != INVALID_POINTER_ID){
float nfX, nfY, nsX, nsY;
nsX = event.getX(event.findPointerIndex(ptrID1));
nsY = event.getY(event.findPointerIndex(ptrID1));
nfX = event.getX(event.findPointerIndex(ptrID2));
nfY = event.getY(event.findPointerIndex(ptrID2));
mAngle = angleBetweenLines(fX, fY, sX, sY, nfX, nfY, nsX, nsY);
if (mListener != null) {
mListener.OnRotation(this);
}
}
break;
case MotionEvent.ACTION_UP:
ptrID1 = INVALID_POINTER_ID;
break;
case MotionEvent.ACTION_POINTER_UP:
ptrID2 = INVALID_POINTER_ID;
break;
case MotionEvent.ACTION_CANCEL:
ptrID1 = INVALID_POINTER_ID;
ptrID2 = INVALID_POINTER_ID;
break;
}
return true;
}
private float angleBetweenLines (float fX, float fY, float sX, float sY, float nfX, float nfY, float nsX, float nsY)
{
float angle1 = (float) Math.atan2( (fY - sY), (fX - sX) );
float angle2 = (float) Math.atan2( (nfY - nsY), (nfX - nsX) );
float angle = ((float)Math.toDegrees(angle1 - angle2)) % 360;
if (angle < -180.f) angle += 360.0f;
if (angle > 180.f) angle -= 360.0f;
return angle;
}
public static interface OnRotationGestureListener {
public void OnRotation(RotationGestureDetector rotationDetector);
}
}
Подробнее здесь: https://stackoverflow.com/questions/790 ... rotate-the
Используя просмотр изображения в масштабе подвыборки, как я могу добавить жест вращения? (поверните изображение жестом д ⇐ Android
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Поверните последнее значение массива, чтобы оно стало первым элементом без вращения ключей.
Anonymous » » в форуме Php - 0 Ответы
- 18 Просмотры
-
Последнее сообщение Anonymous
-
-
-
SwiftUI — жест перетаскивания блокирует жест прокрутки только на iPhone 11
Anonymous » » в форуме IOS - 0 Ответы
- 24 Просмотры
-
Последнее сообщение Anonymous
-