Ich habe endlich eine Antwort darauf gefunden! Es ist ein bisschen hacky, aber nicht zu viel. Die einzigen Nachteile sind:
- Es verwendet eine 3.0+ API. Ernsthaft, obwohl Google, was ist der Sinn der Veröffentlichung neuer Versionen von Android, wenn wir sie nicht verwenden können? /schimpfen.
- Sie müssen die
MenuItem
s durch Ihre eigene View
ersetzen. Ein ImageView
ist dem Standard ziemlich ähnlich, aber es fehlen Merkmale wie langes Drücken, um ein Tool-Tipp zu sehen, und wahrscheinlich andere Dinge.
- Ich habe es nicht viel getestet.
Ok, hier ist, wie wir es machen. Ändern Sie Ihre Activity
‚s onCreateOptionsMenu()
etwas wie folgt aus:
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;
}
Und dann haben Sie eine Funktion, die aktualisiert Ihre hilfreiche Anweisungen mit dem Standort der Taste anzeigen und neu zeichnet es:
private void informButtonLocation(int cx, int cy)
{
MyHelpView v = (MyHelpView)findViewById(R.id.instructions);
v.setText("Click this button.");
v.setTarget(cx, cy);
}
Schließlich machen Sie Ihre fancy schmancy custom view, die einen Pfeil in die Nähe des Buttons zeichnet. In Ihrer onDraw
Methode können Sie die Bildschirmkoordinaten zurück in Canvas
Koordinaten mit der gleichen getLocationOnScreen
Funktion konvertieren.Etwas wie folgt aus:
@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);
}
(Aber natürlich müssen Sie auf die Leinwand Größe den Zielort Clip). Wenn Sie dieselbe Methode wie Google verwenden, bei der Sie eine Ansicht über den gesamten Bildschirm einblenden, müssen Sie sich keine Gedanken darüber machen, aber es ist aufdringlicher. Googles Methode verwendet definitiv keine privaten APIs (erstaunlich). Überprüfen Sie Cling.java
im Launcher2-Code.
Übrigens, wenn Sie sich die Quelle für ähnliche Implementierung von Google für den Launcher ansehen (sie nennen die Anweisungen Bildschirm a Cling
aus irgendeinem Grund), können Sie sehen, dass es noch hacky ist. Sie verwenden grundsätzlich absolute Bildschirmpositionen, die durch das verwendete Layout bestimmt werden.
Hoffe das hilft den Menschen!
Das funktioniert eigentlich gut! Obwohl die Zeit bereits vorbei ist, um für mich nützlich zu sein (ich habe bereits meine eigene Lösung benutzt, siehe unten) und eine Änderung der App ist momentan keine Option. Aber ich hoffe, es wird anderen Menschen in der Zukunft helfen! Gute Antwort! – Pieter888
Der addOnLayoutChangeListener wird nur von Honeycomb unterstützt. Es wird nicht mit alten APIs funktionieren. –
Ich habe jetzt die Koordinaten - aber wie zeichne ich oben auf ein Fragment? – Skynet