JavascriptProva

venerdì 12 agosto 2016

Ricerche sul bottone isolato: primo successo

WindowManager cosa è?
Proviamo a istanziare un oggetto di tipo WindowManager. Ho reso WindowManager wm come variabile di istanza.
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Immagine immagine=new Immagine(this);
        wm=(WindowManager)this.getSystemService(Context.WINDOW_SERVICE);
        wm.addView(immagine);
Ottengo un errore perché il metodo addView prevede necessariamente due parametri di cui uno i parametri.
Devo quindi studiare WindowManager.LayoutParams.
Vediamoli!

Soprattutto, quanti parametri hanno questi LayoutParams?
Qui ne figurano cinque.
  1. larghezza
  2. altezza
  3. tipo
  4. flags
  5. format
Come vengono specificati?
        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
                0,
//              WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
//                      | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
                PixelFormat.TRANSLUCENT);
Ci provo.
Ci si aggiunge anche la proprietà Gravity.
        params=new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
                0,
                PixelFormat.TRANSLUCENT);
        params.gravity= Gravity.RIGHT | Gravity.TOP;
(scritti da me).

E ora ci provo...

Niente da fare!

Mi rendo conto che si tratta di un Service, non di un'Activity.
Costruisco un Service.
Il codice è posto nel metodo onCreate.

E funziona!!!

Continuazione dello studio per i bottoni isolati

Bene.
Ho capito che quella parte del codice non è altro che la creazione di una classe che estende View con il codice per il disegno su di essa.

La parte fondamentale del codice è questa:
    @Override
    public void onCreate() {
        super.onCreate();
        Toast.makeText(getBaseContext(),"onCreate", Toast.LENGTH_LONG).show();
        mView = new HUDView(this);
        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
                0,
//              WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
//                      | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
                PixelFormat.TRANSLUCENT);
        params.gravity = Gravity.RIGHT | Gravity.TOP;
        params.setTitle("Load Average");
        WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
        wm.addView(mView, params);
Prima viene istanziata la classe derivata dalla View:
mView = new HUDView(this);
quindi viene aggiunta non al layout principale, ma a un oggetto di classe WindowManager, dopo una "preparazione" specifica.
Vediamo di analizzarla...

Vengono settati dei parametri di tipo WindowManager.LayoutParams.
Quindi viene istanziato un oggetto di classe WindowManager.
E' necessario andare a vedere le due classi WindowManager e WindowManager.LayoutParams.

Primo ripasso di Paint, Canvas e onDraw

Ecco.
Il passo fondamentale è overridare onDraw.

Però prima bisogna fare una distinzione.
  • Cosa disegnare (Canvas);
  • Come disegnare (Paint).
Dunque prima bisogna creare il Paint, per decidere come disegnare, quindi il Canvas provvederà il cosa disegnare.

Vediamo se per istanziare un oggetto della classe Paint è sufficiente un costruttore senza parametri:
Paint paint=new Paint();
Non ottengo segnalazioni di errore, e per ora ci siamo.

Quindi attribuisco delle proprietà a questo Paint.
        Paint paint=new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(Color.RED);
...forse può bastare.
Ora si overridda onDraw, con Canvas per parametro, come si overridda qualunque metodo.
Ma un'activity non ha come metodo onDraw...

Creo una classe che estende View.
public class Immagine extends View {
}
Mi viene fatta la richiesta del costruttore...
public class Immagine extends View {
    public Immagine(Context context) {
        super(context);
    }
}
Mi conviene quindi istanziare Paint nel costruttore:
public class Immagine extends View {
    public Immagine(Context context) {
        super(context);
        Paint paint=new Paint();
    }
}
E quindi ricominciare il discorso dell'overriddare onDraw.
    @Override
    protected void onDraw(Canvas canvas){
        super.onDraw(canvas);
    }
Rimetto le proprietà al Paint:
        Paint paint=new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(Color.RED);
E ora vediamo se possiamo disegnare qualcosa integrando onDraw: scopro che devo usare nuovamente l'oggetto paint istanziato, e visto che mi trovo in un'altra funzione devo mettere la variabile di questa all'inizio della classe.
    @Override
    protected void onDraw(Canvas canvas){
        super.onDraw(canvas);
        canvas.drawCircle(100,100,50,paint);
    }
}
E vediamo...

Istanzio una view della mia classe:
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        Immagine immagine=new Immagine(this);
        

    }
}
e poi vado...

Bene: non succede niente!
Credo di aver dimenticato qualcosa...

Ecco, sì, ho dimenticato di aggiungere la View al RelativeLayout.
Chiamando questo mainLayout, otteniamo:
public class MainActivity extends AppCompatActivity {

    RelativeLayout mainLayout;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mainLayout = (RelativeLayout)findViewById(R.id.mainLayout);
        Immagine immagine=new Immagine(this);
        mainLayout.addView(immagine);


    }
}
E adesso funziona: ho un cerchio rosso sulla mia activity.

Approccio al "button isolato"

Credo di aver trovato il codice che mi interessa per quel pulsantino isolato che sovrasta tutto...

Analizziamo il codice traducendolo in termini umani...

public class HUD extends Service {
    HUDView mView;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
Viene creato un semplice Service, con il relativo metodo obbligatorio da istanziare onBind... e la dichiarazione di una variabile mView di tipo HUDView. Che tipo sarà questo? Presumibilmente una classe creata ad hoc. Andiamo a cercarla?

Eccola:
class HUDView extends ViewGroup {
    private Paint mLoadPaint;

    public HUDView(Context context) {
        super(context);
        Toast.makeText(getContext(),"HUDView", Toast.LENGTH_LONG).show();

        mLoadPaint = new Paint();
        mLoadPaint.setAntiAlias(true);
        mLoadPaint.setTextSize(10);
        mLoadPaint.setARGB(255, 255, 0, 0);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawText("Hello World", 5, 15, mLoadPaint);
    }

    @Override
    protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //return super.onTouchEvent(event);
        Toast.makeText(getContext(),"onTouchEvent", Toast.LENGTH_LONG).show();
        return true;
    }
}
Spostiamo il focus su questa.
 private Paint mLoadPaint;
 private Paint mLoadPaint;
Viene dichiarata una variabile di tipo Paint.
E dato che non ricordo bene come funziona tutto il complesso delle istruzioni coinvolgenti Paint, Canvas e onDraw è bene che vada a rivedermelo.


Tengo presente il mio riferimento.
Il focus si sposta su Paint, Canvas e onDraw.

giovedì 11 agosto 2016

Giocherellando con la Toolbar

Ora vorrei rendermi conto di questa nuova struttura dell'activity
Che cosa è il CoordinatorLayout?
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.example.antonello.studiofab.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        android:src="@android:drawable/ic_dialog_email" />

</android.support.design.widget.CoordinatorLayout> 
E' quello che avvolge il tutto.
Dentro di esso sono contenuti:
  1. AppBarLayout
  2. content_main
  3. FloatingActionButton
A sua volta AppBarLayout comprende la ToolBar.

Vediamo di trovare qualche definizione.


Bene.
Prendiamo in considerazione AppBarOverlay.
    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout> 
Ora Toolbar è presa in considerazione nel codice Java.
Vediamo...

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
Solo queste, di cui una è l'istanziazione della variabile Toolbar.
Che significa SetSupportActionBar?
Vediamo.

Praticamente serve solo per far sì che questa Toolbar funzioni da ActionBar.
Ah, ecco, ci sono altri metodi:
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        toolbar.setSubtitle("Ciao, ciccio");
Ecco, ho provato a modificare le dimensioni della Toolbar:
    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>




Funziona!

Ora cerco di modificarne anche il colore...
    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:background="#FAA"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>




Perfetto!

Floating Action Button, primi approcci.

Mi conviene fare uno studio del Floating Point, adesso.

Veniamo a esaminare il codice.
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
All'azione click segue questa fantomatica Snackbar che sarebbe uno spazio che si apre sotto all'activity.
E poi setAction... Il codice mi giunge nuovo.
Meglio andare a vedere...

Ecco: intanto ho commentizzato tutta la parte relativa alla Snackbar, e ho creato come codice un semplice Toast:
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(getApplicationContext(),"Ciao floating button",Toast.LENGTH_LONG).show();
                /*Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();*/
            }
        });
Adesso trovo conferma di quanto avevo capito, che la Snackbar è un erede un po' più complesso del Toast.
Vado a provarla...

La scommentizzo e ci gioco un po'...

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                Snackbar.make(view, "Questa è la Snackbar con la sua faccia di cazzo", Snackbar.LENGTH_LONG)
                        .setAction("AZIONEEEE!!!", null).show();
            }
        });
E vediamo il risultato di questi giochini...



Ecco, non mi viene invece "Azioneeee", forse perché c'è quel null davanti...

Vediamo come si agisce su quel null...

Si istanzia un'interfaccia eventListener in forma anonima.
Provo...

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
               
                Snackbar.make(view, "Questa è la Snackbar con la sua faccia di cazzo", Snackbar.LENGTH_LONG)
                        .setAction("AZIONEEEE!!!", new View.OnClickListener() {

                            @Override
                            public void onClick(View v) {
                                Toast.makeText(getApplicationContext(),"Toast derivato dalla Snackbar",Toast.LENGTH_LONG).show();
                            }
                        }).show();
            }
        });
Ecco...



Come volevasi realizzare!

Disabilitare i tasti Recent Tasks e Indietro

Ho trovato il modo di disabilitare sia il tasto Recent Tasks sia il tasto Indietro.
La cosa va sperimentata.
 @Override
 protected void onPause() {
  super.onPause();
  ActivityManager activityManager = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
  activityManager.moveTaskToFront(getTaskId(), 0);
 }

 @Override
 public void onBackPressed(){
Il primo blocca il tasto Recent Tasks, il secondo metodo blocca il tasto Indietro.

Con tutta la ricerca fatta per trovare questi due metodi, è bene conservarli scrupolosamente.