Cuối cùng tôi đã tìm thấy câu trả lời cho điều này! Đó là một chút hacky, nhưng không quá nhiều. Nhược điểm duy nhất là:
- Nó sử dụng API 3.0+. Nghiêm túc mặc dù Google, điểm phát hành phiên bản Android mới là gì nếu chúng ta không thể sử dụng chúng?/rant.
- Bạn phải thay thế số
MenuItem
bằng số View
của riêng bạn. An ImageView
khá giống với tiêu chuẩn nhưng nó bỏ qua các tính năng như nhấn và giữ đầu công cụ, và có thể là những thứ khác.
- Tôi chưa thử nghiệm rất nhiều.
Ok, đây là cách chúng tôi thực hiện. Thay đổi Activity
's onCreateOptionsMenu()
một cái gì đó như thế này của bạn:
View mAddListingButton;
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.activity_main, menu);
// Find the menu item we are interested in.
MenuItem it = menu.findItem(R.id.item_new_listing);
// Create a new view to replace the standard one.
// It would be nice if we could just *get* the standard one
// but unfortunately it.getActionView() returns null.
// actionButtonStyle makes the 'pressed' state work.
ImageView button = new ImageView(this, null, android.R.attr.actionButtonStyle);
button.setImageResource(R.drawable.ic_action_add_listing);
// The onClick attributes in the menu resource no longer work (I assume since
// we passed null as the attribute list when creating this button.
button.setOnClickListener(this);
// Ok, now listen for when layouting is finished and the button is in position.
button.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom)
{
// Apparently this can be called before layout is finished, so ignore it.
// Remember also that it might never be called with sane values, for example
// if your action button is pushed into the "more" menu thing.
if (left == 0 && top == 0 && right == 0 && bottom == 0)
return;
// This is the only way to get the absolute position on the screen.
// The parameters passed to this function are relative to the containing View
// and v.getX/Y() return 0.
int[] location = new int[2];
v.getLocationOnScreen(location);
// Ok, now we know the centre location of the button in screen coordinates!
informButtonLocation(location[0] + (right-left)/2, location[1] + (bottom-top)/2);
}
});
it.setActionView(button);
mAddListingButton = it.getActionView();
return true;
}
Và sau đó bạn có một chức năng cập nhật hướng dẫn hữu ích của bạn xem xung quanh vị trí của các nút và vẽ lại nó:
private void informButtonLocation(int cx, int cy)
{
MyHelpView v = (MyHelpView)findViewById(R.id.instructions);
v.setText("Click this button.");
v.setTarget(cx, cy);
}
Cuối cùng làm cho bạn ưa thích schmancy tùy chỉnh xem mà rút ra một mũi tên để (gần) nút. Trong phương thức onDraw
của bạn, bạn có thể chuyển đổi tọa độ màn hình trở lại Canvas
tọa độ sử dụng cùng chức năng getLocationOnScreen
.Một cái gì đó như thế này:
@Override
public void onDraw(Canvas canvas)
{
int[] location = new int[2];
getLocationOnScreen(location);
canvas.drawColor(Color.WHITE);
mPaint.setColor(Color.BLACK);
mPaint.setTextSize(40);
mPaint.setAntiAlias(true);
mPaint.setTextAlign(Align.CENTER);
canvas.drawText(mText, getWidth()/2, getHeight()/2, mPaint);
// Crappy line that isn't positioned right at all and has no arrowhead.
if (mTargetX != -1 && mTargetY != -1)
canvas.drawLine(getWidth()/2, getHeight()/2,
mTargetX - location[0], mTargetY - location[1], mPaint);
}
(Nhưng rõ ràng bạn phải cắt vị trí mục tiêu vào kích thước Canvas). Nếu bạn đi cho cùng một phương pháp như Google, nơi bạn che phủ một cái nhìn trên toàn bộ màn hình, bạn sẽ không phải lo lắng về điều đó, nhưng nó là xâm nhập hơn. Phương pháp của Google chắc chắn không sử dụng bất kỳ API riêng tư nào (đáng ngạc nhiên). Kiểm tra Cling.java
trong mã Launcher2.
Ngẫu nhiên, nếu bạn nhìn vào nguồn để thực hiện tương tự của Google này cho trình khởi chạy (họ gọi màn hình hướng dẫn là Cling
vì một số lý do), bạn có thể thấy rằng nó còn khó hiểu hơn. Về cơ bản, họ sử dụng các vị trí màn hình tuyệt đối được xác định theo bố cục nào đang được sử dụng.
Hy vọng điều này sẽ giúp mọi người!
Điều này thực sự hoạt động tốt! Mặc dù thời gian đã qua để nó có ích cho tôi (tôi đã sử dụng giải pháp của riêng mình, xem bên dưới) và việc thay đổi ứng dụng không phải là một tùy chọn ngay bây giờ. Nhưng tôi hy vọng nó sẽ giúp những người khác trong tương lai! Câu trả lời chính xác! – Pieter888
addOnLayoutChangeListener chỉ được hỗ trợ từ Honeycomb. nó sẽ không hoạt động trên các API cũ. –
Tôi có tọa độ ngay bây giờ - nhưng làm thế nào để vẽ trên đầu trang của một mảnh? – Skynet