JavascriptProva

sabato 13 agosto 2016

Movimento di un oggetto nell'ambito di una activity.

Per il posizionamento dell'immagine nella finestra: voglio vedere se in WindowManager.LayoutParams vi sono indicazioni per il posizionamento preciso in base a un sistema di coordinate.
Ho già provato con setX() e non funziona.
E se provassi con setRawX()?
Proviamo...

Non esiste proprio. Devo fare una ricerca su WindowManager.LayoutParams. Ecco, ho trovato: esistono le proprietà param.x e param.y, nelle quali però la x esprime il posizionamento relativo a quello in cui l'oggetto viene posizionato inizialmente.
        Immagine immagine=new Immagine(this);

        WindowManager wm=(WindowManager)getSystemService(WINDOW_SERVICE);
                WindowManager.LayoutParams params=new WindowManager.LayoutParams(
                200,
                200,
                WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
                        WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
                PixelFormat.TRANSPARENT);
        params.x=100;
        wm.addView(immagine, params);
(sempre in onCreate).
L'oggetto appare spostato di 100 rispetto al centro dove è stato caricato inizialmente.
Se è così, allora conviene metterlo in alto a sinistra, così il posizionamento relativo dovrebbe diventare assoluto facilitando il compito.

Ho fatto un po' di prove, e tutto è ok.

Ora provo a buttare giù qualcosa che lo sposti.


Con gli strumenti classici non mi sembra possibile spostare un oggetto posizionato direttamente sullo schermo.
Ma prima, a scopo formativo, è bene che mi ristudi un sistema per muovere oggetti entro un'activity.

Come funzionava quello per scrollare un'immagine entro una ImageView?
Ripasso!


Innanzitutto creo una classe:
public class Immagine extends ImageView {

    Context context;
    public Immagine(Context context) {
        super(context);
        this.context=context;
    }
}
Ora voglio metterci un'immagine da risorse.
Prendo un'immagine e la copio nelle risorse, come facevo per Eclipse.

Fatto!

Ora devo inserirla nella mia classe che eredita ImageView.
public class Immagine extends ImageView {

    Context context;
    public Immagine(Context context) {
        super(context);
        this.context=context;
        
        setImageResource(R.drawable.pupazzo);
    }
}
Devo istanziare un oggetto di questa classe, ovviamente...
In MainActivity:
public class MainActivity extends AppCompatActivity {

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

        mainLayout=(RelativeLayout)findViewById(R.id.mainLayout);
        immagine=new Immagine(this);
        mainLayout.addView(immagine);
        
    }

}
(meglio istanziare oggetti dichiarandone le variabili come variabili di istanza anziché come variabili di metodo, locali) E vediamo il risultato...

Bene, ho ottenuto un'immagine molto grande.
Come fare per ridimensionarla?
public class MainActivity extends AppCompatActivity {

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

        mainLayout=(RelativeLayout)findViewById(R.id.mainLayout);
        immagine=new Immagine(this);

        mainLayout.addView(immagine);
        immagine.getLayoutParams().width=100;

    }

}
Se metto quest'ultima riga prima dell'aggiunta dell'immagine a mainLayout ottengo un errore NullPointerException perché l'immagine non esiste ancora non essendo ancora stata aggiunta).


Per demarcare l'immagine dal resto, coloro l'activity principale in modo diverso dal bianco.

Bene, sono riuscito alla fine a posizionare l'immagine, non senza qualche problemino dovuto al fatto che non ricordo lo ScaleType da impostare all'immagine.
Alla fine il codice è questo:
public class MainActivity extends AppCompatActivity {

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

        mainLayout=(RelativeLayout)findViewById(R.id.mainLayout);
        immagine=new Immagine(this);
        immagine.setScaleType(ImageView.ScaleType.FIT_START);
        immagine.setY(0);
        mainLayout.addView(immagine);
        immagine.getLayoutParams().width=200;
        immagine.getLayoutParams().height=200;

    }

}
Per il momento tralascio quel FIT_START, agirò su di esso solo se ci saranno problemi per quanto riguarda lo scrolling.

Ora voglio iniziare, non ricordando bene i codici, dalle cose più semplici: imposto la cosa in modo tale che al semplice tocco la coordinata X cambi.

        immagine.setOnTouchListener(new View.OnTouchListener(){

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                v.setX(100);
                return true;
            }
        });
E riesce perfettamente.
Dunque, facciamo che al movimento i valori attuali di X e Y (tipo float) vengano immagazzinati in due variabili, dopo aver calcolato lo spostamento in rapporto ai valori precedenti delle due variabili.
La prima variabile va impostata all'azione DOWN anziché MOVE.


Sì, ho realizzato lo spostamento, ma non c'è correlazione fra lo spostamento della figura e lo spostamento del mio dito.
Forse il RelativeLayout non fornisce, con il setX e il setY, le giuste coordinate.
Infatti ho ritrovato un mio vecchio codice in cui usavo parametri derivati dal RelativeLayout, e li prendevo a ogni getAction dell'evento Touch.
Provo a rifare adesso la stessa cosa...

Ecco, ho ristudiato il mio vecchio codice.
Il principio è che
  1. Il punto di contatto viene preso una volta sola.
  2. All'azione DOWN viene rilevata la distanza fra il punto di contatto e il margine dell'oggetto.
  3. All'azione MOVE l'oggetto viene riposizionato in base alla distanza del margine dal punto di contatto.
public class MainActivity extends AppCompatActivity {

    float deltaX,deltaY;
    float X,Y;
    RelativeLayout mainLayout;
    Immagine immagine;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mainLayout=(RelativeLayout)findViewById(R.id.mainLayout);
        immagine=new Immagine(this);
        immagine.setScaleType(ImageView.ScaleType.FIT_START);
        RelativeLayout.LayoutParams rl=new RelativeLayout.LayoutParams(0,0);
        mainLayout.addView(immagine,rl);
        immagine.getLayoutParams().width=200;
        immagine.getLayoutParams().height=200;


        immagine.setOnTouchListener(new View.OnTouchListener(){

            public boolean onTouch(View v, MotionEvent event) {

                X=event.getRawX();
                Y=event.getRawY();

                switch(event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) v.getLayoutParams();
                        deltaX = X - lp.leftMargin;
                        deltaY = Y - lp.topMargin;
                        break;

                    case MotionEvent.ACTION_MOVE:
                        lp = (RelativeLayout.LayoutParams) v.getLayoutParams();
                        lp.leftMargin = (int) (X - deltaX);
                        lp.topMargin = (int) (Y - deltaY);
                        v.setLayoutParams(lp);
                        break;
                }

                return true;
            }
        });
    }



}

Nessun commento:

Posta un commento