Làm cách nào để tôi có thể đặt động vị trí xem trong Android?


102

Làm cách nào để thay đổi vị trí xem thông qua mã? Như thay đổi vị trí X, Y của nó. Nó có khả thi không?

Câu trả lời:


117

Đối với bất kỳ thứ gì bên dưới Honeycomb (API Cấp 11), bạn sẽ phải sử dụng setLayoutParams(...) .

Nếu bạn có thể giới hạn hỗ trợ của bạn để Honeycomb và lên bạn có thể sử dụng setX(...), setY(...), setLeft(...), setTop(...)vv


40
từ tài liệu của setTop () developer.android.com/reference/android/view/… : sets the top position of this view relative to its parent. This method is meant to be called by the layout system and should not generally be called otherwise, because the property may be changed at any time by the layout.- vì vậy có lẽ đó không phải là một ý tưởng hay;)
katzenhut

47

Có, bạn có thể đặt động vị trí xem trong Android. Tương tự như vậy bạn có một ImageViewtrong LinearLayoutcác xml của bạn file.So bạn có thể thiết lập vị trí của mình thông qua LayoutParams.Nhưng chắc chắn để đưa LayoutParamstheo cách bố trí thực hiện trong xml của bạn file.There là khác nhau LayoutParamstheo cách bố trí thực hiện.

Đây là mã để đặt:

    LayoutParams layoutParams=new LayoutParams(int width, int height);
    layoutParams.setMargins(int left, int top, int right, int bottom);
    imageView.setLayoutParams(layoutParams);

Tôi hy vọng nó sẽ hữu ích cho bạn để thiết lập vị trí.


15
cũng lưu ý rằng bạn phải nhập android.widget.LinearLayout.LayoutParams; vì mặc định là LayoutParams của ViewGroup
David T.

Điều này dường như không hoạt động trên Android 8+. bạn đã đối mặt với một vấn đề tương tự?
MyFlashLab, 24/09/18

Bất kỳ ý tưởng nào tại sao các nhà thiết kế Andriod lại gặp rắc rối như vậy để ngăn các nhà lập trình sử dụng X, Y để định vị mọi thứ. Cuối cùng mọi thứ phải được vẽ theo cách đó. Điều này cho thấy rằng Android đang được thiết kế bởi những người không thể viết mã.
Paul McCarthy

33

Đã có các câu trả lời hợp lệ khác nhau, nhưng dường như không có câu trả lời nào gợi ý chính xác (các) phương pháp nên sử dụng trong trường hợp nào, ngoại trừ các hạn chế cấp API tương ứng:

  • Nếu bạn có thể đợi một chu kỳ bố cục và nhóm chế độ xem chính hỗ trợ MarginLayoutParams(hoặc một lớp con), hãy đặt marginLeft/ cho marginTopphù hợp.

  • Nếu bạn cần thay đổi vị trí ngay lập tức và liên tục (ví dụ: đối với neo PopupMenu), hãy gọi thêm layout(l, t, r, b)với cùng tọa độ. Điều này ưu tiên những gì hệ thống bố trí sẽ xác nhận sau đó.

  • Đối với các thay đổi tức thời (tạm thời) (chẳng hạn như hoạt ảnh), hãy sử dụng setX()/ setY()thay thế. Trong trường hợp kích thước gốc không phụ thuộc vào WRAP_CHILDREN, bạn có thể sử dụng setX()/ setY()độc quyền.

  • Không bao giờ sử dụng setLeft()/ setRight()/ setBottom()/ setTop(), xem bên dưới.

Bối cảnh : Các trường mLeft/ mTop/ mBottom/ mRightđược điền từ LayoutParams tương ứng trong layout (). Bố cục được gọi ngầm và không đồng bộ bởi hệ thống bố cục chế độ xem Android. Do đó, đặt vị trí MarginLayoutParamscó vẻ là cách an toàn và sạch sẽ nhất để đặt vị trí vĩnh viễn. Tuy nhiên, độ trễ của bố cục không đồng bộ có thể là một vấn đề trong một số trường hợp, chẳng hạn như khi sử dụng Chế độ xem để hiển thị con trỏ và nó phải được định vị lại và phục vụ như một neo PopupMenu cùng một lúc. Trong trường hợp này, gọi điện layout()hoạt động tốt đối với tôi.

Các vấn đề với setLeft()setTop()là:

  • Gọi cho họ một mình là không đủ - bạn cũng cần gọi setRight()setBottom()để tránh kéo dài hoặc thu nhỏ tầm nhìn.

  • Việc triển khai các phương pháp này có vẻ tương đối phức tạp (= thực hiện một số công việc để giải thích các thay đổi về kích thước chế độ xem do mỗi phương pháp gây ra)

  • Chúng dường như gây ra các vấn đề lạ với các trường nhập liệu: Bàn phím số mềm EditText đôi khi không cho phép các chữ số

setX()setY()hoạt động bên ngoài hệ thống bố cục, và các giá trị tương ứng được coi là phần bù bổ sung cho các giá trị bên trái / trên cùng / bên phải được xác định bởi hệ thống bố cục, thay đổi chế độ xem theo đó. Chúng dường như đã được thêm vào cho hình ảnh động (nơi cần phải có hiệu ứng tức thì mà không cần trải qua chu trình bố cục).


Xin chào Stefan. Bạn có thể tư vấn một vài cuốn sách hoặc bài báo mà tôi có thể hiểu cách hoạt động của hệ thống bố cục Android. Tôi hiểu chuỗi lệnh gọi layout () onMeasure () onDraw () đó, nhưng muốn biết chi tiết hơn. Cảm ơn trước
Sergey Brazhnik

Đáng tiếc là tôi không thể - tài liệu tham khảo tốt nhất và dứt khoát nhất có vẻ là O mã nguồn Android thực tế :)
Stefan Haustein

Tôi sử dụng setY để thay đổi chế độ xem, nó thay đổi trong chu kỳ bố trí tiếp theo, không phải ngay lập tức?
tín hiệu

Làm thế nào bạn xác định điều này?
Stefan Haustein

Cần chỉ ra rằng marginLeftcó thể được thiết lập bằng cách sử dụngsetLayoutParams với một new FrameLayout.LayoutParams(width, height)mà bạn thiết lậpmarginLeft
lucidbrot

18

Có một thư viện tên là NineOldAndroids , cho phép bạn sử dụng thư viện hoạt hình Honeycomb cho đến hết phiên bản một.

Điều này có nghĩa là bạn có thể xác định trái, phải, dịchX / Y với một giao diện hơi khác.

Đây là cách nó làm việc:

ViewHelper.setTranslationX(view, 50f);

Bạn chỉ cần sử dụng các phương thức tĩnh từ lớp ViewHelper, chuyển chế độ xem và giá trị nào bạn muốn đặt nó.


16

Tôi muốn khuyên bạn nên sử dụng setTranslationXsetTranslationY. Tôi chỉ mới bắt đầu làm việc này, nhưng đây có vẻ là cách an toàn nhất và được ưa thích hơn để di chuyển một góc nhìn. Tôi đoán nó phụ thuộc rất nhiều vào chính xác những gì bạn đang cố gắng làm, nhưng điều này đang hoạt động tốt đối với tôi đối với hoạt hình 2D.


13

Bạn có thể thử sử dụng các phương pháp sau, nếu đang sử dụng HoneyComb Sdk (API Cấp 11).

view.setX(float x);

Tham số x là vị trí trực quan x của khung nhìn này.

view.setY(float y);

Tham số y là vị trí trực quan y của khung nhìn này.

Tôi hy vọng nó sẽ hữu ích cho bạn. :)


4
Tôi đang làm việc trên 2.2 Froyo và những phương pháp này không có sẵn trong đó.
Arun Badole

7

Để được hỗ trợ cho tất cả các cấp API, bạn có thể sử dụng như sau:

ViewPropertyAnimator.animate(view).translationYBy(-yourY).translationXBy(-yourX).setDuration(0);

Bởi vì ông muốn thay đổi vị trí và giải pháp trên là tốt hơn và không cần hình ảnh động
FireZenk

Ngoài ra, bản dịch có thể khiến chế độ xem chuyển sang (một phần) ngoài màn hình
mewa

4

Đặt vị trí bên trái của chế độ xem này so với vị trí gốc của nó:

view.setLeft(int leftPosition);

Đặt đúng vị trí của chế độ xem này so với vị trí gốc của nó:

view.setRight(int rightPosition);

Đặt vị trí trên cùng của chế độ xem này so với vị trí gốc của nó:

view.setTop(int topPosition);

Đặt vị trí dưới cùng của chế độ xem này so với vị trí gốc của nó:

view.setBottom(int bottomPositon);

Các phương thức trên được sử dụng để thiết lập vị trí của khung nhìn liên quan đến cha của nó.


Xin lỗi, các phương pháp này không khả dụng. Bạn có thể gửi cho tôi bất kỳ mã nào không?
Arun Badole

4
"Phương thức này được gọi bởi hệ thống bố cục và nói chung không nên được gọi theo cách khác, bởi vì thuộc tính có thể được bố trí thay đổi bất kỳ lúc nào."
GDanger

4

Sử dụng LayoutParams. Nếu bạn đang sử dụng LinearLayout, bạn phải nhập android.widget.LinearLayout.LayoutParams, nếu không hãy nhập phiên bản LayoutParams thích hợp cho bố cục bạn đang sử dụng, nếu không sẽ gây ra ClassCastException , sau đó:

LayoutParams layoutParams = new LayoutParams(int width, int height);
layoutParams.setMargins(int left, int top, int right, int bottom);
imageView.setLayoutParams(layoutParams);

NB: Lưu ý rằng bạn cũng có thể sử dụng imageView.setLeft (int dim), NHƯNG ĐIỀU NÀY KHÔNG thiết lập vị trí của thành phần, nó sẽ chỉ đặt vị trí của đường viền bên trái của thành phần, phần còn lại sẽ giữ nguyên vị trí .


vậy làm cách nào chúng ta có thể di chuyển chế độ xem đến vị trí cụ thể mà không ảnh hưởng đến chế độ xem ban đầu?
james

Tôi không chắc mình đã hiểu vấn đề của bạn vì nếu bạn muốn di chuyển một chế độ xem, bạn sẽ thay đổi nó bởi thực tế là bạn đang di chuyển nó. Dù sao, nếu bạn muốn di chuyển một chế độ xem sang một chế độ xem khác độc lập với nó, bạn có thể cần một chế độ xem FrameLayout làm mờ bố cục chính của bạn, sau đó, bên trong nó, bạn có thể đặt các chế độ xem độc lập của mình (rõ ràng nếu bạn muốn nó di chuyển dưới chế độ xem chính của bạn. phải đặt FrameLayout trước khung chính của bạn)
Alessandro Muzzi

3

Sử dụng RelativeLayout, đặt chế độ xem của bạn vào đó, lấy RelativeLayout.LayoutParamsđối tượng từ chế độ xem của bạn và đặt lề khi bạn cần. Sau đó, hãy gọi requestLayout()theo quan điểm của bạn. Đây là cách duy nhất tôi biết.


1

Tôi thấy rằng @Stefan Haustein rất gần với trải nghiệm của tôi, nhưng không chắc chắn 100%. Đề xuất của tôi là:

  • setLeft()/ setRight()/ setBottom()/ setTop()đôi khi sẽ không hoạt động.
  • Nếu bạn muốn tạm thời đặt một vị trí (ví dụ: để thực hiện hoạt ảnh, không bị ảnh hưởng đến phân cấp) khi chế độ xem được thêm và hiển thị , chỉ cần sử dụng setX()/setY() thay thế. (Bạn có thể muốn tìm kiếm nhiều hơn về sự khác biệt setLeft()setX() )
  • Và lưu ý rằng X, Y dường như là tuyệt đối và nó được hỗ trợ bởi AbsoluteLayout hiện không được dùng nữa. Vì vậy, bạn cảm thấy X, Y có khả năng không được hỗ trợ nữa. Và có, nó là, nhưng chỉ một phần. Nó có nghĩa là nếu chế độ xem của bạn được thêm vào, setX (), setY () sẽ hoạt động hoàn hảo ; ngược lại, khi bạn cố gắng thêm một chế độ xem vào bố cục nhóm chế độ xem (ví dụ: FrameLayout, LinearLayout, RelativeLayout), bạn phải đặt LayoutParams của nó bằng marginLeft, marginTop thay thế (setX (), setY () trong trường hợp này đôi khi sẽ không hoạt động).
  • Đặt vị trí của khung nhìn bằng marginLeft và marginTop là một quá trình không đồng bộ . Vì vậy, nó cần một chút thời gian để cập nhật hệ thống phân cấp . Nếu bạn sử dụng chế độ xem ngay sau khi đặt lề cho nó, bạn có thể nhận được giá trị sai .

0

Một điều cần lưu ý với định vị là mỗi chế độ xem có một chỉ mục liên quan đến chế độ xem mẹ của nó. Vì vậy, nếu bạn có bố cục tuyến tính với ba chế độ xem phụ, mỗi chế độ xem phụ sẽ có chỉ mục: 0, 1, 2 trong trường hợp trên.

Điều này cho phép bạn thêm chế độ xem vào vị trí cuối cùng (hoặc cuối) trong chế độ xem gốc bằng cách làm như sau:

int childCount = parent.getChildCount();
parentView.addView(newView, childCount);

Ngoài ra, bạn có thể thay thế một chế độ xem bằng cách sử dụng một cái gì đó như sau:

int childIndex = parentView.indexOfChild(childView);
childView.setVisibility(View.GONE);

parentView.addView(newView, childIndex);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.