Android-->View.setX()和.setY()的使用(移动布局,设置布局位置,动态添加View)

示例图:

这里写图片描述


重点在于 从写 了 TouchView,原理是一样的:

public class TouchView extends ImageView {

    public TouchView(Context context) {
        super(context);

        this.setImageResource(R.drawable.ic_launcher);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(100, 100);
    }

    float downX, downY;
    float moveX, moveY;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            downX = event.getRawX();
            downY = event.getRawY();
        }

        if (event.getAction() == MotionEvent.ACTION_MOVE) {
            moveX = event.getRawX();
            moveY = event.getRawY();

            this.setX(getX() + (moveX - downX));
            this.setY(getY() + (moveY - downY));
            downX = moveX;
            downY = moveY;
        }

        return true;// 返回true 表示 处理Touch事件
        // return super.onTouchEvent(event);
    }

}

public class MainActivity extends Activity {


    LinearLayout linear;
    RelativeLayout relative;
    FrameLayout frame;
    AbsoluteLayout absolute;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        linear = (LinearLayout) findViewById(R.id.linear);
        relative = (RelativeLayout) findViewById(R.id.relative);
        frame = (FrameLayout) findViewById(R.id.frame);
        absolute = (AbsoluteLayout) findViewById(R.id.absolute);

        linear.addView(new TouchView(this));
        relative.addView(new TouchView(this));
        frame.addView(new TouchView(this));
        absolute.addView(new TouchView(this));
    }
}

源代码下载地址:http://download.youkuaiyun.com/detail/angcyo/8953263


至此: 文章就结束了,如有疑问: QQ群:274306954 欢迎您的加入.

如下Qt代码每次拖动矩形时会自动执行一次,请问有什么问题?void HI_GraphicsView::mouseMoveEvent(QMouseEvent *event) { // if(m_isTranslate) // { // //获取 // QPointF mouseDelta = event->pos()-m_lastMousePos; // Translate(mouseDelta); // } // m_lastMousePos = event->pos(); QGraphicsView::mouseMoveEvent(event); } void HI_GraphicsView::mousePressEvent(QMouseEvent *event) { if(event->button() == Qt::LeftButton) { m_isTranslate = true; m_lastMousePos = event->pos(); } else if(event->button()==Qt::RightButton) { QPointF point = mapToScene(event->pos()); //只有点击图片时才发送 if (scene()->itemAt(point, transform()) != NULL) { emit m_imageBox->ImageClick(point.x(),point.y()); } } QGraphicsView::mousePressEvent(event); } void HI_GraphicsView::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) m_isTranslate = false; QGraphicsItem *item = NULL; item = m_scene->itemAt(m_lastMousePos,transform()); if(item == NULL) { drawRectangle(mapToScene(m_lastMousePos),mapToScene(event->pos()),"test",Qt::green); } else { if(m_scene->selectedItems().count()==1 && m_scene->selectedItems().at(0)->pos().x()!=0) { QRectF rect = qgraphicsitem_cast<QGraphicsRectItem*>(m_imageItem)->rect(); if(m_imageItem->x()<-rect.x()) m_imageItem->setX(-rect.x()); if(m_imageItem->y()<-rect.y()) m_imageItem->setY(-rect.y()); // ui->spinBoxX->setValue(rect.x() + m_selectItem->x()); // ui->spinBoxY->setValue(rect.y() + m_selectItem->y()); } } QGraphicsView::mouseReleaseEvent(event); }
03-21
#include "Zoom.h" Zoom::Zoom(QWidget* parent) : QWidget(parent) { // 基础设置 setWindowTitle("Zoom Tool"); resize(600, 600); setStyleSheet("background-color: white;"); // 初始化组件,构建一个可以查看操作图片的界面 scrollArea = new QScrollArea(this); imageLabel = new QLabel(scrollArea); imageLabel->setAlignment(Qt::AlignCenter); imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); scrollArea->setWidget(imageLabel); scrollArea->setBackgroundRole(QPalette::Dark); // ===== 添加事件过滤器 ===== scrollArea->viewport()->installEventFilter(this); // 布局 QVBoxLayout* mainLayout = new QVBoxLayout(this); mainLayout->addWidget(scrollArea); // 按钮区域 QHBoxLayout* buttonLayout = new QHBoxLayout(); QPushButton* prevBtn = new QPushButton("前一张"); QPushButton* openBtn = new QPushButton("打开图片"); QPushButton* nextBtn = new QPushButton("后一张"); QPushButton* resetBtn = new QPushButton("恢复"); buttonLayout->addWidget(prevBtn); buttonLayout->addWidget(openBtn); buttonLayout->addWidget(nextBtn); buttonLayout->addWidget(resetBtn); mainLayout->addLayout(buttonLayout); // 坐标显示 QHBoxLayout* coordLayout = new QHBoxLayout(); coordXLabel = new QLabel("X坐标:0"); coordYLabel = new QLabel("Y坐标:0"); // grayLabel = new QLabel("灰度值:0"); coordLayout->addWidget(coordXLabel); coordLayout->addWidget(coordYLabel); //coordLayout->addWidget(grayLabel); mainLayout->addLayout(coordLayout); // 缩放比例标签,右上角的显示缩放比 scaleLabel = new QLabel(this); scaleLabel->setStyleSheet("background-color: rgba(255,255,255,150);"); scaleLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop); scaleLabel->setFixedSize(100, 30); scaleLabel->hide(); // 初始时隐藏,只有在缩放操作时才显示 // 连接信号槽 connect(openBtn, &QPushButton::clicked, this, &Zoom::openImage); connect(resetBtn, &QPushButton::clicked, this, &Zoom::resetImage); connect(prevBtn, &QPushButton::clicked, this, &Zoom::prevImage); connect(nextBtn, &QPushButton::clicked, this, &Zoom::nextImage); // 定时器 scaleTimer = new QTimer(this); scaleTimer->setSingleShot(true); //接定时器的timeout信号到一个lambda函数,当定时器超时时,执行scaleLabel->hide()隐藏标签 connect(scaleTimer, &QTimer::timeout, this, [this]() { scaleLabel->hide(); }); scaleFactor = 1.0; } //实现图片缩放功能 void Zoom::wheelEvent(QWheelEvent* event) { if (image.isNull()) { event->ignore(); return; } // 1. 获取鼠标在视口中的位置(相对于 scrollArea 视口) QPointF mousePos = event->position(); // 2. 计算鼠标在图像中的位置(考虑当前滚动位置缩放比例) QPointF imagePosBefore = QPointF( (mousePos.x() + scrollArea->horizontalScrollBar()->value()) / scaleFactor, (mousePos.y() + scrollArea->verticalScrollBar()->value()) / scaleFactor ); // 3. 计算缩放因子 const double ZOOM_RATIO = 1.1; double angle = event->angleDelta().y(); if (angle == 0) return; double factor = (angle > 0) ? ZOOM_RATIO : (1.0 / ZOOM_RATIO); double newScale = qBound(0.1, scaleFactor * factor, 10.0); if (qFuzzyCompare(newScale, scaleFactor)) { event->accept(); return; } // 4. 应用新缩放比例 QPixmap scaledPixmap = QPixmap::fromImage( image.scaled(image.size() * newScale, Qt::KeepAspectRatio, Qt::SmoothTransformation)); imageLabel->setPixmap(scaledPixmap); imageLabel->resize(scaledPixmap.size()); // 5. 计算新的滚动位置(保持鼠标下的图像点不变) QPointF imagePosAfter = imagePosBefore * newScale; QPoint newScrollPos( qRound(imagePosAfter.x() - mousePos.x()), qRound(imagePosAfter.y() - mousePos.y()) ); // 限制滚动范围 newScrollPos.setX(qMax(0, qMin(imageLabel->width() - scrollArea->viewport()->width(), newScrollPos.x()))); newScrollPos.setY(qMax(0, qMin(imageLabel->height() - scrollArea->viewport()->height(), newScrollPos.y()))); scrollArea->horizontalScrollBar()->setValue(newScrollPos.x()); scrollArea->verticalScrollBar()->setValue(newScrollPos.y()); // 6. 更新缩放比例UI scaleFactor = newScale; scaleLabel->setText(QString("缩放: %1%").arg(qRound(scaleFactor * 100))); scaleLabel->move(10, 10); scaleLabel->show(); scaleTimer->start(5000); event->accept(); } //void Zoom::updateCursorState() { // if (!imageLabel->pixmap().isNull() && // (imageLabel->pixmap().width() > scrollArea->viewport()->width() || // imageLabel->pixmap().height() > scrollArea->viewport()->height())) { // setCursor(Qt::OpenHandCursor); // } else { // setCursor(Qt::ArrowCursor); // } //} bool Zoom::eventFilter(QObject* obj, QEvent* event) { if (obj == scrollArea->viewport() && event->type() == QEvent::Wheel) { // 如果事件发生在视口上,直接调用wheelEvent wheelEvent(static_cast<QWheelEvent*>(event)); return true; // 事件已处理 } return QWidget::eventFilter(obj, event); } //鼠标按下事件 void Zoom::mousePressEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton && !image.isNull()) { // 只要图片存在就允许拖动 dragPos = event->pos(); setCursor(Qt::ClosedHandCursor); } else if (event->button() == Qt::RightButton && !image.isNull()) { // 右键坐标显示 QPoint imagePos = imageLabel->mapFrom(this, event->pos()); if (imageLabel->rect().contains(imagePos)) { QPoint pixelPos = imagePos / scaleFactor; coordXLabel->setText(QString("X坐标:%1").arg(pixelPos.x())); coordYLabel->setText(QString("Y坐标:%1").arg(pixelPos.y())); /* if (image.format() == QImage::Format_RGB32 || image.format() == QImage::Format_ARGB32) { QRgb pixel = image.pixel(pixelPos); int gray = qGray(pixel); grayLabel->setText(QString("灰度值:%1").arg(gray)); }*/ } } } //鼠标移动事件 void Zoom::mouseMoveEvent(QMouseEvent* event) { if ((event->buttons() & Qt::LeftButton) && !dragPos.isNull()) { QPoint delta = dragPos - event->pos(); dragPos = event->pos(); // 直接应用拖动,不检查边界 scrollArea->horizontalScrollBar()->setValue( scrollArea->horizontalScrollBar()->value() + delta.x()); scrollArea->verticalScrollBar()->setValue( scrollArea->verticalScrollBar()->value() + delta.y()); } } //鼠标释放事件 void Zoom::mouseReleaseEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) { dragPos = QPoint(); // 只要图片存在就显示张开的手型光标 if (!image.isNull()) { setCursor(Qt::OpenHandCursor); } else { setCursor(Qt::ArrowCursor); } } } //打开图片文件 void Zoom::openImage() { QString fileName = QFileDialog::getOpenFileName(this, "打开图片", currentFolder, "Images (*.png *.jpg *.bmp)"); if (!fileName.isEmpty()) { // 获取文件夹路径该文件夹下所有图片 QFileInfo fileInfo(fileName); currentFolder = fileInfo.path(); QDir dir(currentFolder); QStringList filters = { "*.png", "*.jpg", "*.bmp" }; imagePaths = dir.entryList(filters, QDir::Files, QDir::Name); // 设置当前图片索引 currentImageIndex = imagePaths.indexOf(fileInfo.fileName()); // 加载图片 loadCurrentImage(); } } // 加载当前图片 void Zoom::loadCurrentImage() { if (currentImageIndex >= 0 && currentImageIndex < imagePaths.size()) { QString imagePath = currentFolder + "/" + imagePaths[currentImageIndex]; image.load(imagePath); if (image.isNull()) { QMessageBox::warning(this, "错误", "无法加载图片"); return; } scaleFactor = 1.0; imageLabel->setPixmap(QPixmap::fromImage(image)); imageLabel->adjustSize(); imageLabel->setAlignment(Qt::AlignCenter); setWindowTitle("Zoom Tool - " + imagePaths[currentImageIndex]); // 只在加载切换图片时调用居中显示自适应缩小 adjustAndCenterImage(); if (!image.isNull()) { setCursor(Qt::OpenHandCursor); } } } //重置图片显示 void Zoom::resetImage() { if (image.isNull()) return; scaleFactor = 1.0; imageLabel->setPixmap(QPixmap::fromImage(image)); imageLabel->adjustSize(); imageLabel->setAlignment(Qt::AlignCenter); // 只在恢复时调用居中显示自适应缩小 adjustAndCenterImage(); if (!image.isNull()) { setCursor(Qt::OpenHandCursor); } else { setCursor(Qt::ArrowCursor); } scaleLabel->hide(); } void Zoom::adjustAndCenterImage() { if (image.isNull()) return; // 获取视图图像尺寸 QSize viewSize = scrollArea->viewport()->size(); QSize imageSize = image.size(); // 计算适合的缩放比例 double widthRatio = (double)viewSize.width() / imageSize.width(); double heightRatio = (double)viewSize.height() / imageSize.height(); scaleFactor = qMin(widthRatio, heightRatio); // 如果图像小于视图,保持原始大小 if (imageSize.width() < viewSize.width() && imageSize.height() < viewSize.height()) { scaleFactor = 1.0; } // 应用缩放 QPixmap scaledPixmap = QPixmap::fromImage( image.scaled(image.size() * scaleFactor, Qt::KeepAspectRatio, Qt::SmoothTransformation)); imageLabel->setPixmap(scaledPixmap); imageLabel->resize(scaledPixmap.size()); imageLabel->setAlignment(Qt::AlignCenter); // 强制重新计算布局 scrollArea->widget()->setContentsMargins(0, 0, 0, 0); scrollArea->setAlignment(Qt::AlignCenter); // 计算居中位置(考虑滚动区域的实际可用空间) int hMax = qMax(0, imageLabel->width() - viewSize.width()); int vMax = qMax(0, imageLabel->height() - viewSize.height()); // 设置滚动条位置(强制居中) scrollArea->horizontalScrollBar()->setRange(0, hMax); scrollArea->verticalScrollBar()->setRange(0, vMax); scrollArea->horizontalScrollBar()->setValue(hMax / 2); scrollArea->verticalScrollBar()->setValue(vMax / 2); // 显示缩放比例 scaleLabel->setText(QString("缩放: %1%").arg(qRound(scaleFactor * 100))); scaleLabel->move(10, 10); scaleLabel->show(); scaleTimer->start(5000); } // 调整图像显示 //void Zoom::adjustImageToView() { // if (image.isNull()) return; // // // 获取视图图像尺寸 // QSize viewSize = scrollArea->viewport()->size(); // QSize imageSize = image.size(); // // // 计算适合的缩放比例 // double widthRatio = (double)viewSize.width() / imageSize.width(); // double heightRatio = (double)viewSize.height() / imageSize.height(); // scaleFactor = qMin(widthRatio, heightRatio); // // // 如果图像小于视图,保持原始大小 // if (imageSize.width() < viewSize.width() && imageSize.height() < viewSize.height()) { // scaleFactor = 1.0; // } // // // 应用缩放 // QPixmap scaledPixmap = QPixmap::fromImage( // image.scaled(image.size() * scaleFactor, // Qt::KeepAspectRatio, // Qt::SmoothTransformation)); // // imageLabel->setPixmap(scaledPixmap); // imageLabel->resize(scaledPixmap.size()); // imageLabel->setAlignment(Qt::AlignCenter); // // // 强制重新计算布局 // scrollArea->widget()->setContentsMargins(0, 0, 0, 0); // scrollArea->setAlignment(Qt::AlignCenter); // // // 显示缩放比例 // scaleLabel->setText(QString("缩放: %1%").arg(qRound(scaleFactor * 100))); // scaleLabel->move(10, 10); // scaleLabel->show(); // scaleTimer->start(5000); //} // 添加前一张图片功能 void Zoom::prevImage() { if (imagePaths.isEmpty()) { QMessageBox::information(this, "提示", "请先打开图片"); return; } currentImageIndex--; if (currentImageIndex < 0) { currentImageIndex = imagePaths.size() - 1; // 循环到最后一张 } loadCurrentImage(); } // 添加后一张图片功能 void Zoom::nextImage() { if (imagePaths.isEmpty()) { QMessageBox::information(this, "提示", "请先打开图片"); return; } currentImageIndex++; if (currentImageIndex >= imagePaths.size()) { currentImageIndex = 0; // 循环到第一张 } loadCurrentImage(); } 以上代码,怎么修改为以鼠标光标为中心点进行缩放,就是在缩放操作时,图像位置,以鼠标所在点为中心,即鼠标所在的图像上那一点,在视窗里保持位置不变,来进行缩放
最新发布
07-15
<think>好的,我现在需要回答用户关于如何在Android动态设置布局的XY坐标的问题。首先,我需要回忆Android开发中有关视图定位的相关知识。用户提到“programmatically”,也就是以编程方式设置,而不是在XML布局文件中设置。 首先,我应该考虑Android中视图的位置控制方式。常用的方法可能有几种,比如使用setX()setY()方法,或者通过修改布局参数(LayoutParams)。不过,不同版本的Android可能支持不同的方法,这需要考虑兼容性。 接下来,我需要确认这些方法的正确性。比如,View类确实有setX()setY()方法,但它们是在API Level 11(Android 3.0)引入的。对于旧版本的支持可能需要使用其他方式,比如设置 margins 或者使用 translationX/Y。但用户的问题中没有提到兼容旧版本,所以可能可以默认使用较新的方法。 另外,LayoutParams中的设置可能适用于父布局的类型。例如,如果父布局是RelativeLayout,可以设置leftMargintopMargin,或者使用类似addRule的方法。而如果是FrameLayout,可能需要使用lefttop参数,或者使用setX/Y直接调整视图的位置。 需要注意的是,直接设置XY坐标可能会与布局的测量排列机制产生冲突。例如,如果父布局重新进行布局,可能会导致设置位置被覆盖。因此,可能需要将视图的位置设置为绝对位置,或者确保在布局过程中不会改变这些值。 用户提供的引用中有提到GenericDraweeHierarchyBuilder的设置,这可能Fresco库相关,但用户的问题是关于设置坐标,所以可能需要忽略这部分引用。另一个引用提到以编程方式打开选择器的选项,这可能与问题无关,但需要确认是否有相关内容可以帮助回答。 接下来,我需要组织回答的结构。首先,明确可以通过setX()setY()方法直接设置坐标,但需要检查API级别。其次,对于旧版本,可以使用setTranslationX()setTranslationY(),但这会影响视图的平移而不是绝对位置。另外,修改LayoutParams的leftMargintopMargin也是一种方法,但需要根据父布局的类型来调整。 还需要提到,在Android中,视图的位置通常由布局管理器控制,直接设置坐标可能会影响布局的稳定性,因此需要谨慎使用。可能还需要给出示例代码,比如如何获取View布局参数并修改,或者直接调用setX/Y方法。 最后,用户可能需要处理的是如何确保设置后的坐标在屏幕上的正确位置,可能需要考虑屏幕密度、单位转换等问题,比如将dp转换为像素。不过用户的问题主要集中在设置方法上,可能暂时不需要深入讨论单位转换。 总结回答步骤: 1. 使用setX()setY()方法(API 11+)。 2. 使用translationX/Y进行平移。 3. 通过LayoutParams设置边距或其他参数,适用于不同布局类型。 4. 注意事项兼容性问题。 5. 提供代码示例。 需要验证这些方法的正确性,确保代码示例正确无误,并且语法正确。同时,根据用户提供的引用,可能需要引用相关的Android文档或开发者资源,但用户给出的引用似乎不直接相关,可能不需要引用。</think>在Android动态设置视图的XY坐标可以通过以下方法实现: ### 方法1:使用`setX()``setY()`(API Level 11+) 适用于Android 3.0及以上系统: ```java View view = findViewById(R.id.your_view); view.setX(100); // 单位:像素 view.setY(200); ``` 注意需将dp值转换为像素,可使用: ```java float density = getResources().getDisplayMetrics().density; int xPx = (int)(20 * density); // 20dp转像素 view.setX(xPx); ``` ### 方法2:通过布局参数调整(兼容旧版本) 适用于所有API级别,需根据父容器类型选择对应参数: ```java View view = findViewById(R.id.your_view); FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) view.getLayoutParams(); params.leftMargin = xPx; // 相对父容器左边距 params.topMargin = yPx; // 相对父容器顶边距 view.setLayoutParams(params); ``` ### 方法3:使用`setTranslationX()``setTranslationY()` 实现视图平移效果(不改变布局参数): ```java view.setTranslationX(50); // 向右平移50像素 view.setTranslationY(-30); // 向上平移30像素 ``` ### 注意事项 1. **坐标系差异**:`setX/Y()`基于父容器坐标系,而`setTranslationX/Y()`是视图当前位置的偏移量 2. **布局冲突**:直接设置坐标可能被父布局的`onLayout()`覆盖,建议在自定义布局中处理 3. **性能优化**:频繁修改坐标时应使用属性动画(如`ObjectAnimator`)而非直接操作
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值