2012-09-05 7 views
7

Ich verwende NineOldAndroids Bibliothek, um mein benutzerdefiniertes Layout zu skalieren.Android ViewGroup.setScaleX() bewirkt, dass die Ansicht abgeschnitten wird

public class MyLayout extends FrameLayout { 
    // LayoutParams.MATCH_PARENT and all. 
    ... 
    @Override 
    public boolean setPositionAndScale(ViewGroup v, PositionAndScale pas, PointInfo pi) { 
    ... 
    mScale = pas.getScale(); 
    ViewHelper.setScaleX(this, mScale); 
    ViewHelper.setScaleY(this, mScale); 
    } 
} 

Ich habe FrameLayout und AbsoluteLayout versucht. Alle haben den gleichen Effekt. Wenn mScale < 1.0Skalierung/Zoom funktioniert aber Teil des Layouts ist abgeschnitten.

mScale = 1.0:

mScale = 1.0

mScale < 1.0:Skalierung/Zoomen funktioniert aber das Layout ist abgeschnitten

mScale < 1.0

, wie ich dieses Problem beheben kann?

Bearbeiten: Das Bild wurde auf ICS aufgenommen. Also ich denke nicht, dass es NineOldAndroids Problem ist.

+0

Wie erwarten Sie, dass die Ausgabe aussieht? – alanv

+0

Etwas wie MapView. Dass das Layout ('MyLayout') den gesamten Bildschirm ausfüllt und nicht wie im 2. Bild abgeschnitten ist. LayoutParam von MyLayout sind gesetzt Match_parent. – user802421

Antwort

2

Falls jemand in die gleiche Situation wie ich kam. ich am Ende mit diesem Ansatz:

protected void setScale(float scale, boolean updateView) { 
    mScale = scale; 
    if (updateView) { 
     LayoutParams params = getLayoutParams(); 
     onUpdateScale(scale, params); 
     setLayoutParams(params); 
    } 
} 

protected void onUpdateScale(float scale, LayoutParams params) { 
    params.leftMargin = (int) (mModel.getX() * scale); 
    params.topMargin = (int) (mModel.getY() * scale); 
    params.width = (int) (mModel.getWidth() * scale); 
    params.height = (int) (mModel.getHeight() * scale); 
} 
+0

Ist dieser Ansatz schnell? Ich meine, machst du zu viele Updates mit etwas wie einer Geste zu skalieren, oder skalierst du nur einmal? –

+0

Ich habe noch keine Benchmarks oder TraceView ausgeführt, aber es funktioniert gut auf Xoom 1 und Nexus S. Die Anforderungen waren, dass das Verschieben und Skalieren kontinuierlich (wie Google Maps) und nicht sobald die Interaktion beendet ist (wie das Zoomen von OSMTracker)). – user802421

+0

Also, kein Flackern? (+1 wenn du nein antwortest :-)) –

1

Wenn ich Ihr Problem richtig verstanden habe, skalieren Sie eine Ansichtsgruppe und erwarten, dass die enthaltenen Ansichten entsprechend skaliert werden. Es funktioniert nicht so: Sie skalieren die Ansichtsgruppe und sie ändert die Größe, aber die untergeordneten Ansichten nicht.

Skalieren Sie einfach alle Unteransichten. Trotzdem bin ich mir nicht sicher, ob Texte und Bilder automatisch skaliert werden. Was Sie wollen, ist Zoom, nicht skalieren. Versuchen Sie this reference.

+0

Was ist der Unterschied zwischen Zoom und Skalierung? Das Bild 2 zeigt, dass das Zoomen/Skalieren funktioniert (mScale ~ 0.8).Es ist nur so, dass die ViewGroup abgeschnitten ist. – user802421

+0

Nun, Ihre Referenz funktioniert genauso wie mein Code. – user802421

+0

Ich ziehe meine Antwort dann zurück, Entschuldigung für den Lärm. – alexfernandez

1

Seit API Level 11 verfügt die Klasse View über die Methoden setScaleX() und setScaleY(), die erwartungsgemäß funktionieren und auch Teilansichten der skalierten Ansicht skalieren. Also, wenn das eine Möglichkeit für Sie wäre, lassen Sie die Bibliothek fallen und tun Sie einfach

+0

Ich habe das schon mal probiert. Es hat den gleichen Clipping-Effekt. Tatsächlich ist die Bibliothek nur ein Proxy. Auf ICS rufen die NineOldAndroids einfach dieselbe Methode auf. – user802421

+0

@ user802421 Dies könnte helfen: http://stackoverflow.com/q/14415035/350040 – sergio91pt

0

Verwendung ViewGroup.layout. Es kann der einfachste Weg sein, ViewGroup zu skalieren (& move).

3

Das übergeordnete Element Ihrer Ansicht muss die Eigenschaft android:clipChildren deaktiviert haben (aus der Layoutdatei oder mit setClipChildren(false)).

Aber mit dieser Methode erhalten Sie die Berührungsereignisse nicht außerhalb der Grenzen des Ansichtsclips. Sie können umgehen, indem Sie sie von Ihrer Aktivität senden oder eine benutzerdefinierte ViewGroup Eltern schreiben.

Ich benutze einen anderen Hack, der in meinem Fall zu funktionieren scheint, der Trick besteht darin, Ihre eigene Transformationsmatrix zu verwalten. Dann müssen Sie eine Menge von ViewGroup Methode überladen, um es zu arbeiten. Zum Beispiel:

@Override 
protected void dispatchDraw(Canvas canvas) { 
    Log.d(TAG, "dispatchDraw " + canvas); 
    canvas.save(); 
    canvas.concat(mMatrix); 
    super.dispatchDraw(canvas); 
    canvas.restore();  
} 


@Override 
public boolean dispatchTouchEvent(MotionEvent ev) { 
    Log.d(TAG, "dispatchTouchEvent " + ev); 
    ev.transform(getInvMatrix()); // 
    return super.dispatchTouchEvent(ev); 

} 

private Matrix getInvMatrix() 
{ 
    if(!mTmpMatIsInvMat) 
     mMatrix.invert(mTmpMat); 
    mTmpMatIsInvMat = true; 
    return mTmpMat; 
} 
+0

Sie können die Matrix aus der Ansicht abrufen. view.getMatrix() invertiere es dann, m.invert (m) und benutze das, um das Bewegungsereignis zu skalieren. – Tatarize

+0

Ich habe ein paar verschiedene Hacks aus gefälschten Ansichten ausprobiert, die einfach den rohen Touch weitergaben, der dann durch die Views-Matrix transformiert wurde. Und das einzige, was jemals auf der gesamten Hardware, auf die ich Zugriff habe, konsistent funktioniert, ist die Pflege meiner eigenen Matrix und die Verwendung dieser, um die Bewegungsereignisse, die Ansicht und die Rechtecke zu verfälschen. – Tatarize