Ho un RelativeLayout posto all'interno di una ScrollView:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:fillViewport="true" android:id="@+id/scrollView" android:layout_width="match_parent" android:layout_height="match_parent" > <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:id="@+id/mainLayout" android:background="#aef" tools:context="com.example.comunicatore.MainActivity" > </RelativeLayout> </ScrollView>Adesso voglio esercitarmi a riscrivere il codice secondo il quale vengono creati dei layout ognuno contenente un'immagine presa nelle risorse, spostabili nell'ambito della ScrollView.
Ossia la schermata può scorrere e nell'ambito della schermata si può eseguire il drag-drop di questi layout.
Cancello il codice che ho scritto e riscrivo.
Parto da questo:
import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.ScrollView; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }Ho già un id attribuito al RelativeLayout e alla ScrollView che lo contiene, nel file xml.
Vado:
inizio con la dichiarazione della ScrollView e del RelativeLayout
//DICHIARAZIONI---DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD ScrollView scrollView; RelativeLayout mainLayout; //TERMINE DICHIARAZIONI---DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD(mi creo delle sezioni distinte nell'ambito del codice per poterlo rileggere più agevolmente quando diventerà complicato).
Ora inizializzo scrollView e mainLayout:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //INIZIALIZZAZIONI----IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII scrollView=(ScrollView)findViewById(R.id.scrollView); mainLayout=(RelativeLayout)findViewById(R.id.mainLayout); //TERMINE INIZIALIZZAZIONI----IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIE adesso procedo alla creazione a runtime di un layout:
per prima cosa lo dichiaro nella sezione DICHIARAZIONI (preferisco che il suo scope sia diffuso a tutte le parti del codice):
//DICHIARAZIONI---DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD ScrollView scrollView; RelativeLayout mainLayout; LinearLayout layout; //TERMINE DICHIARAZIONI---DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDichiaro la ImageView che figurerà all'interno del layout:
//DICHIARAZIONI---DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD ScrollView scrollView; RelativeLayout mainLayout; LinearLayout layout; ImageView imageView; //TERMINE DICHIARAZIONI---DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDopo aver creato il layout, creo una ImageView che vi andrà messa dentro:
//CODICE DI ONCREATE----CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC layout=new LinearLayout(this); imageView=new ImageView(this); //TERMINE CODICE DI ONCREATE----CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCE ora devo prendere l'immagine dalle risorse e metterla nella ImageView.
Ricorro al codice che riduce le dimensioni delle immagini:
layout=new LinearLayout(this);
imageView=new ImageView(this);
BitmapFactory.Options opzioni=new BitmapFactory.Options();
opzioni.inJustDecodeBounds=true;
BitmapFactory.decodeResource(getResources(), R.drawable.faciadecul,opzioni);
int fattore=1;
while(opzioni.outWidth/fattore>100 && opzioni.outHeight/fattore>100){
fattore*=2;
}
opzioni.inJustDecodeBounds=false;
opzioni.inSampleSize=fattore;
Bitmap bmp=BitmapFactory.decodeResource(getResources(), R.drawable.faciadecul,opzioni);
imageView.setImageBitmap(bmp);
E quindi pongo la ImageView entro il Layout.
layout=new LinearLayout(this);
imageView=new ImageView(this);
BitmapFactory.Options opzioni=new BitmapFactory.Options();
opzioni.inJustDecodeBounds=true;
BitmapFactory.decodeResource(getResources(), R.drawable.faciadecul,opzioni);
int fattore=1;
while(opzioni.outWidth/fattore>100 && opzioni.outHeight/fattore>100){
fattore*=2;
}
opzioni.inJustDecodeBounds=false;
opzioni.inSampleSize=fattore;
Bitmap bmp=BitmapFactory.decodeResource(getResources(), R.drawable.faciadecul,opzioni);
imageView.setImageBitmap(bmp);
layout.addView(imageView)
Ora imposto le proprietà del layout e lo aggiungo a mainLayout.
layout=new LinearLayout(this); imageView=new ImageView(this); BitmapFactory.Options opzioni=new BitmapFactory.Options(); opzioni.inJustDecodeBounds=true; BitmapFactory.decodeResource(getResources(), R.drawable.faciadecul,opzioni); int fattore=1; while(opzioni.outWidth/fattore>100 && opzioni.outHeight/fattore>100){ fattore*=2; } opzioni.inJustDecodeBounds=false; opzioni.inSampleSize=fattore; Bitmap bmp=BitmapFactory.decodeResource(getResources(), R.drawable.faciadecul,opzioni); imageView.setImageBitmap(bmp); layout.addView(imageView); RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT); mainLayout.addView(layout);
Ora lancio il tutto, scritto di getto, per verificare la mia abilità...
Perfetto! Funziona alla perfezione!
Giocherellando sulle dimensioni dell'immagine verifico che la scrollView funzioni anch'essa, e risulta funzionante.
Ora metto il codice per rendere spostabile il layout con l'immagine.
Creo una sezione //LISTENERS. Dichiaro un OnTouchListener nella sezione DICHIARAZIONI...
//DICHIARAZIONI---DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD ScrollView scrollView; RelativeLayout mainLayout; LinearLayout layout; ImageView imageView; View.OnTouchListener layoutTouchListener; //TERMINE DICHIARAZIONI---DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDe vado a inizializzarlo nella sezione LISTENERS:
//LISTENERS----LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL layoutTouchListener=new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return false; } }; //TERMINE LISTENERS----LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLQuindi mi assicuro che all'evento Touch, sempre, venga rilevata la posizione del mouse (o meglio del dito)
Dichiaro le coordinate del mouse/dito nella sezione DICHIARAZIONI:
ScrollView scrollView;
RelativeLayout mainLayout;
LinearLayout layout;
ImageView imageView;
View.OnTouchListener layoutTouchListener;
int X,Y;
E rilevo nell'evento OnTouch le coordinate:
layoutTouchListener=new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
X=(int)event.getRawX();
Y=(int)event.getRawY();
return false;
}
};
Ora bisogna calcolare la differenza fra la posizione del mouse/dito e quella del layout nel momento in cui va a toccare (evento ACTION_DOWN).
Dichiaro due altre variabili: DeltaX e DeltaY, in cui metterò le differenze delle coordinate dito-layout.
ScrollView scrollView;
RelativeLayout mainLayout;
LinearLayout layout;
ImageView imageView;
View.OnTouchListener layoutTouchListener;
int X,Y;
int deltaX, deltaY;
e vado a dar loro il valore.Per fare questo, nel codice del listener, devo desumere le coordinate del layout stesso, mediante i LayoutParameters:
layoutTouchListener=new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
X=(int)event.getRawX();
Y=(int)event.getRawY();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
RelativeLayout.LayoutParams params=(RelativeLayout.LayoutParams)v.getLayoutParams();
deltaX=X-params.leftMargin;
deltaY=Y-params.topMargin;
break;
}
return false;
}
};
Ottenuta la differenza, a ogni movimento del mouse/dito devo porre le coordinate del layout a valori pari alle coordinate del dito meno le coordinate del layout.
layoutTouchListener=new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
X=(int)event.getRawX();
Y=(int)event.getRawY();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
RelativeLayout.LayoutParams params=(RelativeLayout.LayoutParams)v.getLayoutParams();
deltaX=X-params.leftMargin;
deltaY=Y-params.topMargin;
break;
case MotionEvent.ACTION_MOVE:
params=(RelativeLayout.LayoutParams)v.getLayoutParams();
params.leftMargin=X-deltaX;
params.topMargin=Y-deltaY;
v.setLayoutParams(params);
break;
}
return false;
}
};
(l'evento OnTouch si ripete sempre anche durante il movimento, per cui X e Y vengono continuamente rilevate).Ora devo attribuire il Listener al layout, però! Ho lanciato l'applicazione dimenticando di farlo, e ovviamente non funzionava...
layout=new LinearLayout(this); imageView=new ImageView(this); BitmapFactory.Options opzioni=new BitmapFactory.Options(); opzioni.inJustDecodeBounds=true; BitmapFactory.decodeResource(getResources(), R.drawable.faciadecul,opzioni); int fattore=1; while(opzioni.outWidth/fattore>100 || opzioni.outHeight/fattore>100){ fattore*=2; } opzioni.inJustDecodeBounds=false; opzioni.inSampleSize=fattore; Bitmap bmp=BitmapFactory.decodeResource(getResources(), R.drawable.faciadecul,opzioni); imageView.setImageBitmap(bmp); layout.addView(imageView); RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT); layout.setOnTouchListener(layoutTouchListener); mainLayout.addView(layout); Non funziona ancora!
Provo a cambiare il false dell'evento OnTouch a true:
layoutTouchListener=new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
X=(int)event.getRawX();
Y=(int)event.getRawY();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
RelativeLayout.LayoutParams params=(RelativeLayout.LayoutParams)v.getLayoutParams();
deltaX=X-params.leftMargin;
deltaY=Y-params.topMargin;
break;
case MotionEvent.ACTION_MOVE:
params=(RelativeLayout.LayoutParams)v.getLayoutParams();
params.leftMargin=X-deltaX;
params.topMargin=Y-deltaY;
v.setLayoutParams(params);
break;
}
return true;
}
};
E parte!!!Probabilmente con il false l'evento "bubblava" al mainLayout.
Però insorge un nuovo problema! Finché non viene "sfottuta" la scrollView, il layout con l'immagine si sposta agevolmente, ma quando lo porto in giù oltrepassando il limite della "schermata", allora entra in azione la scrollView, che funziona, ma una volta azionata non riesco più a muovere il layout, che nel trascinamento col mouse/dito ha strani comportamenti.
Probabilmente ciò è dovuto al fatto che la scrollView viene manipolata quando tocco il layout. Così devo mettere in azione un blocco della scrollView nel momento in cui sto "draggando" il layout.
Ci provo con un magico metodo di nome "request..." e non ricordo più come, da porre nel codice dell'evento OnTouch.
Lo ritrovo con l'Intellisense...
layoutTouchListener=new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
scrollView.requestDisallowInterceptTouchEvent(false);
X=(int)event.getRawX();
Y=(int)event.getRawY();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
RelativeLayout.LayoutParams params=(RelativeLayout.LayoutParams)v.getLayoutParams();
deltaX=X-params.leftMargin;
deltaY=Y-params.topMargin;
break;
case MotionEvent.ACTION_MOVE:
params=(RelativeLayout.LayoutParams)v.getLayoutParams();
params.leftMargin=X-deltaX;
params.topMargin=Y-deltaY;
v.setLayoutParams(params);
break;
}
return true;
}
};
Eccolo! Rilancio l'applicazione e vediamo ora come va...
Va male, esattamente come prima, perché quel metodo dovevo impostarlo a true!
layoutTouchListener=new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { scrollView.requestDisallowInterceptTouchEvent(true); X=(int)event.getRawX(); Y=(int)event.getRawY(); switch(event.getAction()){ case MotionEvent.ACTION_DOWN: RelativeLayout.LayoutParams params=(RelativeLayout.LayoutParams)v.getLayoutParams(); deltaX=X-params.leftMargin; deltaY=Y-params.topMargin; break; case MotionEvent.ACTION_MOVE: params=(RelativeLayout.LayoutParams)v.getLayoutParams(); params.leftMargin=X-deltaX; params.topMargin=Y-deltaY; v.setLayoutParams(params); break; } return true; } };Ora è praticamente perfetto!!!
Nessun commento:
Posta un commento