Ricerca…


Creazione di viste personalizzate

Se hai bisogno di una vista completamente personalizzata, dovrai creare sottoclassi View (la superclasse di tutte le viste Android) e fornire i tuoi onMeasure(...) ridimensionamento personalizzato ( onMeasure(...) ) e drawing ( onDraw(...) ):

  1. Crea il tuo scheletro di visualizzazione personalizzato: questo è fondamentalmente lo stesso per ogni vista personalizzata. Qui creiamo lo scheletro per una vista personalizzata che può disegnare uno smiley, chiamato SmileyView :

    public class SmileyView extends View {
        private Paint mCirclePaint;
        private Paint mEyeAndMouthPaint;
    
        private float mCenterX;
        private float mCenterY;
        private float mRadius;
        private RectF mArcBounds = new RectF();
    
        public SmileyView(Context context) {
            this(context, null, 0);
        }
    
        public SmileyView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public SmileyView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            initPaints();
        }
    
        private void initPaints() {/* ... */}
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {/* ... */}
    
        @Override
        protected void onDraw(Canvas canvas) {/* ... */}
    }
    
  2. Inizializza le tue pitture: gli oggetti Paint sono i pennelli della tua tela virtuale che definiscono il modo in cui i tuoi oggetti geometrici sono resi (es. Colore, stile di riempimento e tratto, ecc.). Qui creiamo due Paint , una vernice gialla riempita per il cerchio e una vernice nera per gli occhi e la bocca:

    private void initPaints() {
        mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mCirclePaint.setStyle(Paint.Style.FILL);
        mCirclePaint.setColor(Color.YELLOW);
        mEyeAndMouthPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mEyeAndMouthPaint.setStyle(Paint.Style.STROKE);
        mEyeAndMouthPaint.setStrokeWidth(16 * getResources().getDisplayMetrics().density);
        mEyeAndMouthPaint.setStrokeCap(Paint.Cap.ROUND);
        mEyeAndMouthPaint.setColor(Color.BLACK);
    }
    
  3. Implementa il tuo metodo onMeasure(...) : è necessario in modo che i layout principali (ad esempio FrameLayout ) possano allineare correttamente la vista personalizzata. Fornisce un set di measureSpecs che è possibile utilizzare per determinare l'altezza e la larghezza della vista. Qui creiamo un quadrato assicurandoti che l'altezza e la larghezza siano le stesse:

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int w = MeasureSpec.getSize(widthMeasureSpec);
        int h = MeasureSpec.getSize(heightMeasureSpec);
    
        int size = Math.min(w, h);
        setMeasuredDimension(size, size);
    }
    

    Nota che onMeasure(...) deve contenere almeno una chiamata a setMeasuredDimension(..) altrimenti la tua vista personalizzata si bloccherà con un IllegalStateException .

  4. Implementa il tuo metodo onSizeChanged(...) : questo ti consente di catturare l'altezza e la larghezza attuali della tua vista personalizzata per regolare correttamente il tuo codice di rendering. Qui calcoliamo solo il nostro centro e il nostro raggio:

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        mCenterX = w / 2f;
        mCenterY = h / 2f;
        mRadius = Math.min(w, h) / 2f;
    }
    
  5. Implementa il tuo metodo onDraw(...) : è qui che implementa il rendering effettivo della tua vista. Fornisce un oggetto Canvas cui puoi disegnare (consulta la documentazione ufficiale su Canvas per tutti i metodi di disegno disponibili).

    @Override
    protected void onDraw(Canvas canvas) {
        // draw face
        canvas.drawCircle(mCenterX, mCenterY, mRadius, mCirclePaint);
        // draw eyes
        float eyeRadius = mRadius / 5f;
        float eyeOffsetX = mRadius / 3f;
        float eyeOffsetY = mRadius / 3f;
        canvas.drawCircle(mCenterX - eyeOffsetX, mCenterY - eyeOffsetY, eyeRadius, mEyeAndMouthPaint);
        canvas.drawCircle(mCenterX + eyeOffsetX, mCenterY - eyeOffsetY, eyeRadius, mEyeAndMouthPaint);
        // draw mouth
        float mouthInset = mRadius /3f;
        mArcBounds.set(mouthInset, mouthInset, mRadius * 2 - mouthInset, mRadius * 2 - mouthInset);
        canvas.drawArc(mArcBounds, 45f, 90f, false, mEyeAndMouthPaint);
    }
    
  6. Aggiungi la tua vista personalizzata a un layout: la visualizzazione personalizzata ora può essere inclusa in qualsiasi file di layout che hai. Qui lo avvolgiamo in un FrameLayout :

    <FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <com.example.app.SmileyView
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </FrameLayout>
    

Si noti che è consigliabile creare il progetto dopo aver completato il codice di visualizzazione. Senza costruirlo, non potrai vedere la vista su una schermata di anteprima in Android Studio.

Dopo aver messo tutto insieme, dovresti essere accolto con la seguente schermata dopo aver avviato l'attività contenente il layout di cui sopra:

SmileyView utilizzato all'interno dell'attività

Aggiunta di attributi alle viste

Le visualizzazioni personalizzate possono anche utilizzare attributi personalizzati che possono essere utilizzati nei file di risorse del layout Android. Per aggiungere attributi alla tua vista personalizzata devi fare quanto segue:

  1. Definisci il nome e il tipo dei tuoi attributi: questo viene fatto all'interno di res/values/attrs.xml ( res/values/attrs.xml se necessario). Il seguente file definisce un attributo colore per il colore del viso della nostra emoticon e un attributo enum per l'espressione della faccina:

    <resources>
        <declare-styleable name="SmileyView">
            <attr name="smileyColor" format="color" />
            <attr name="smileyExpression" format="enum">
                <enum name="happy" value="0"/>
                <enum name="sad" value="1"/>
            </attr>
        </declare-styleable>
        <!-- attributes for other views -->
    </resources>
    
  2. Usa i tuoi attributi all'interno del tuo layout: questo può essere fatto all'interno di qualsiasi file di layout che usa la tua vista personalizzata. Il seguente file di layout crea uno schermo con un sorriso giallo felice:

    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_height="match_parent"
        android:layout_width="match_parent">
        
        <com.example.app.SmileyView
            android:layout_height="56dp"
            android:layout_width="56dp"
            app:smileyColor="#ffff00"
            app:smileyExpression="happy" />
    </FrameLayout>
    

    Suggerimento: gli attributi personalizzati non funzionano con gli tools: prefisso in Android Studio 2.1 e versioni precedenti (e possibilmente nelle versioni future). In questo esempio, sostituendo l' app:smileyColor con gli tools:smileyColor comporterebbe che smileyColor non venisse impostato né in fase di esecuzione né in fase di progettazione.

  3. Leggi i tuoi attributi: questo viene fatto all'interno del tuo codice sorgente di visualizzazione personalizzato. Il seguente frammento di SmileyView mostra come SmileyView gli attributi:

    public class SmileyView extends View {
        // ...
    
        public SmileyView(Context context) {
            this(context, null);
        }
    
        public SmileyView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public SmileyView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            
            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SmileyView, defStyleAttr, 0);
            mFaceColor = a.getColor(R.styleable.SmileyView_smileyColor, Color.TRANSPARENT);
            mFaceExpression = a.getInteger(R.styleable.SmileyView_smileyExpression, Expression.HAPPY);
            // Important: always recycle the TypedArray
            a.recycle();
    
            // initPaints(); ...
        }
    }
    
  4. (Facoltativo) Aggiungi stile predefinito: questo viene fatto aggiungendo uno stile con i valori predefiniti e caricandolo all'interno della tua vista personalizzata. Il seguente stile predefinito di smiley rappresenta un felice giallo:

    <!-- styles.xml -->
    <style name="DefaultSmileyStyle">
        <item name="smileyColor">#ffff00</item>
        <item name="smileyExpression">happy</item>
    </style>
    

    Che viene applicato nel nostro SmileyView aggiungendolo come l'ultimo parametro della chiamata per obtainStyledAttributes (vedere codice nel passaggio 3):

    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SmileyView, defStyleAttr, R.style.DefaultSmileyViewStyle);
    

    Si noti che qualsiasi valore di attributo impostato nel file di layout gonfiato (vedere il codice nel passaggio 2) sostituirà i valori corrispondenti dello stile predefinito.

  5. (Facoltativo) Fornire stili all'interno di temi: ciò viene fatto aggiungendo un nuovo attributo di riferimento di stile che può essere utilizzato all'interno dei temi e fornendo uno stile per tale attributo. Qui semplicemente smileyStyle nostro attributo di riferimento smileyStyle :

    <!-- attrs.xml -->
    <attr name="smileyStyle" format="reference" />
    

    Che quindi forniamo uno stile per il nostro tema dell'app (qui riutilizziamo solo lo stile predefinito del passaggio 4):

    <!-- themes.xml -->
    <style name="AppTheme" parent="AppBaseTheme">
        <item name="smileyStyle">@style/DefaultSmileyStyle</item>
    </style>
    

Creazione di una vista composta

Una vista composta è un ViewGroup personalizzato trattato come una singola vista dal codice del programma circostante. Tale ViewGroup può essere davvero utile nella progettazione DDD , perché può corrispondere a un aggregato, in questo esempio, un contatto. Può essere riutilizzato ovunque venga visualizzato il contatto.

Ciò significa che il codice del controller circostante, un'attività, un frammento o un adattatore, può semplicemente passare l'oggetto dati alla vista senza selezionarlo in un numero di diversi widget dell'interfaccia utente.

Ciò facilita il riutilizzo del codice e rende il design migliore secondo i principi SOLID .

Il layout XML

Questo di solito è dove inizi. Hai un po 'di XML esistente che ti ritrovi a riutilizzare, forse come un <include/> . Estraetelo in un file XML separato e avvolgete il tag radice in un elemento <merge> :

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

        <ImageView
            android:id="@+id/photo"
            android:layout_width="48dp"
            android:layout_height="48dp"
            android:layout_alignParentRight="true" />

        <TextView
            android:id="@+id/name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_toLeftOf="@id/photo" />

        <TextView
            android:id="@+id/phone_number"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/name"
            android:layout_toLeftOf="@id/photo" />
</merge>

Questo file XML continua a funzionare perfettamente nell'editor di layout di Android Studio. Puoi trattarlo come qualsiasi altro layout.

Il composto ViewGroup

Una volta ottenuto il file XML, creare il gruppo di viste personalizzato.

import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.ImageView;
import android.widget.TextView;

import myapp.R;

/**
 * A compound view to show contacts.
 *
 * This class can be put into an XML layout or instantiated programmatically, it
 * will work correctly either way.
 */
public class ContactView extends RelativeLayout {

    // This class extends RelativeLayout because that comes with an automatic
    // (MATCH_PARENT, MATCH_PARENT) layout for its child item. You can extend
    // the raw android.view.ViewGroup class if you want more control. See the
    // note in the layout XML why you wouldn't want to extend a complex view
    // such as RelativeLayout.

    // 1. Implement superclass constructors.
    public ContactView(Context context) {
        super(context);
        init(context, null);
    }

    // two extra constructors left out to keep the example shorter

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public ContactView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs);
    }

    // 2. Initialize the view by inflating an XML using `this` as parent
    private TextView mName;
    private TextView mPhoneNumber;
    private ImageView mPhoto;

    private void init(Context context, AttributeSet attrs) {
        LayoutInflater.from(context).inflate(R.layout.contact_view, this, true);
        mName = (TextView) findViewById(R.id.name);
        mPhoneNumber = (TextView) findViewById(R.id.phone_number);
        mPhoto = (ImageView) findViewById(R.id.photo);
    }

    // 3. Define a setter that's expressed in your domain model. This is what the example is
    //    all about. All controller code can just invoke this setter instead of fiddling with
    //    lots of strings, visibility options, colors, animations, etc. If you don't use a
    //    custom view, this code will usually end up in a static helper method (bad) or copies 
    //    of this code will be copy-pasted all over the place (worse).
    public void setContact(Contact contact) {
        mName.setText(contact.getName());
        mPhoneNumber.setText(contact.getPhoneNumber());
        if (contact.hasPhoto()) {
            mPhoto.setVisibility(View.VISIBLE);
            mPhoto.setImageBitmap(contact.getPhoto());
        } else {
            mPhoto.setVisibility(View.GONE);
        }
    }
}

Il metodo init(Context, AttributeSet) è il punto in cui leggere gli attributi XML personalizzati come spiegato in Aggiunta di attributi alle viste .

Con questi pezzi sul posto, puoi usarlo nella tua app.

Utilizzo in XML

Ecco un esempio di fragment_contact_info.xml che illustra come mettere un singolo ContactView in cima a un elenco di messaggi:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!-- The compound view becomes like any other view XML element -->
    <myapp.ContactView
        android:id="@+id/contact"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/message_list"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

</LinearLayout>

Uso nel codice

Ecco un esempio di RecyclerView.Adapter che mostra un elenco di contatti. Questo esempio illustra quanto è più pulito il codice del controller quando è completamente privo di manipolazione della vista.

package myapp;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.ViewGroup;

public class ContactsAdapter extends RecyclerView.Adapter<ContactsViewHolder> {

    private final Context context;

    public ContactsAdapter(final Context context) {
        this.context = context;
    }

    @Override
    public ContactsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        ContactView v = new ContactView(context); // <--- this
        return new ContactsViewHolder(v);
    }

    @Override
    public void onBindViewHolder(ContactsViewHolder holder, int position) {
        Contact contact = this.getItem(position);
        holder.setContact(contact);  // <--- this
    }

    static class ContactsViewHolder extends RecyclerView.ViewHolder {

        public ContactsViewHolder(ContactView itemView) {
            super(itemView);
        }

        public void setContact(Contact contact) {
            ((ContactView) itemView).setContact(contact); // <--- this
        }
    }
}

Suggerimenti sulle prestazioni di CustomView

Non assegnare nuovi oggetti in onDraw

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Paint paint = new Paint(); //Do not allocate here
}

Invece di disegnare drawable su tela ...

drawable.setBounds(boundsRect);

drawable.draw(canvas);

Usa una bitmap per disegnare più velocemente:

canvas.drawBitmap(bitmap, srcRect, boundsRect, paint);

Non ridisegnare l'intera vista per aggiornarne solo una piccola parte. Invece ridisegna la parte specifica della vista.

invalidate(boundToBeRefreshed);

Se la tua vista sta facendo un'animazione continua, ad esempio un quadrante che mostra ogni secondo, almeno ferma l'animazione su onStop() dell'attività e ricominciala su onStart() dell'attività.

Non eseguire calcoli all'interno del metodo onDraw di una vista, dovresti invece terminare il disegno prima di chiamare invalidate() . Usando questa tecnica puoi evitare la caduta del fotogramma nella tua vista.

rotazioni

Le operazioni di base di una vista sono traslazione, rotazione, ecc ... Quasi tutti gli sviluppatori hanno affrontato questo problema quando usano bitmap o gradienti nella loro vista personalizzata. Se la vista mostra una vista ruotata e la bitmap deve essere ruotata in quella visualizzazione personalizzata, molti di noi penseranno che sarà costoso. Molti pensano che la rotazione di una bitmap sia molto costosa perché per farlo è necessario tradurre la matrice di pixel della bitmap. Ma la verità è che non è così difficile! Invece di ruotare la bitmap, basta ruotare la tela stessa!

// Save the canvas state
int save = canvas.save();
// Rotate the canvas by providing the  center point as pivot and angle
canvas.rotate(pivotX, pivotY, angle);
// Draw whatever you want
// Basically whatever you draw here will be drawn as per the angle you rotated the canvas
canvas.drawBitmap(...);
// Now restore your your canvas to its original state
canvas.restore(save);
// Unless canvas is restored to its original state, further draw will also be rotated.

Vista composta per SVG / VectorDrawable come drawableRight

Motivo principale per sviluppare questa vista composta è, sotto 5.0 dispositivi non supporta svg in disegnabile all'interno di TextView / EditText. Un altro pro è che possiamo impostare height e width del drawableRight all'interno di EditText . L'ho separato dal mio progetto e creato in un modulo separato.

Nome del modulo: custom_edit_drawable (nome breve per il prefisso-c_d_e)

prefisso "c_d_e_" da utilizzare in modo che le risorse del modulo app non le sovrascrivano per errore. Esempio: il prefisso "abc" è utilizzato da google nella libreria di supporto.

build.gradle

dependencies {
   compile 'com.android.support:appcompat-v7:25.3.1'
}

usa AppCompat> = 23

File di layout: c_e_d_compound_view.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <EditText
        android:id="@+id/edt_search"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="text"
        android:maxLines="1"
        android:paddingEnd="40dp"
        android:paddingLeft="5dp"
        android:paddingRight="40dp"
        android:paddingStart="5dp" />

    <!--make sure you are not using ImageView instead of this-->
    <android.support.v7.widget.AppCompatImageView
        android:id="@+id/drawbleRight_search"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_gravity="right|center_vertical"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp" />
</FrameLayout>

Attributi personalizzati: attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="EditTextWithDrawable">
        <attr name="c_e_d_drawableRightSVG" format="reference" />
        <attr name="c_e_d_hint" format="string" />
        <attr name="c_e_d_textSize" format="dimension" />
        <attr name="c_e_d_textColor" format="color" />
    </declare-styleable>
</resources>

Codice: EditTextWithDrawable.java

public class EditTextWithDrawable extends FrameLayout {
    public AppCompatImageView mDrawableRight;
    public EditText mEditText;

    public EditTextWithDrawable(Context context) {
        super(context);
        init(null);
    }

    public EditTextWithDrawable(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs);
    }

    public EditTextWithDrawable(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public EditTextWithDrawable(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(attrs);
    }

    private void init(AttributeSet attrs) {
        if (attrs != null && !isInEditMode()) {
            LayoutInflater inflater = (LayoutInflater) getContext()
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            inflater.inflate(R.layout.c_e_d_compound_view, this, true);
            mDrawableRight = (AppCompatImageView) ((FrameLayout) getChildAt(0)).getChildAt(1);
            mEditText = (EditText) ((FrameLayout) getChildAt(0)).getChildAt(0);

            TypedArray attributeArray = getContext().obtainStyledAttributes(
                    attrs,
                    R.styleable.EditTextWithDrawable);

            int drawableRes =
                    attributeArray.getResourceId(
                            R.styleable.EditTextWithDrawable_c_e_d_drawableRightSVG, -1);
            if (drawableRes != -1) {
                mDrawableRight.setImageResource(drawableRes);
            }

            mEditText.setHint(attributeArray.getString(
                    R.styleable.EditTextWithDrawable_c_e_d_hint));
            mEditText.setTextColor(attributeArray.getColor(
                    R.styleable.EditTextWithDrawable_c_e_d_textColor, Color.BLACK));
            int textSize = attributeArray.getDimensionPixelSize(R.styleable.EditTextWithDrawable_c_e_d_textSize, 15);
            mEditText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
            android.view.ViewGroup.LayoutParams layoutParams = mDrawableRight.getLayoutParams();
            layoutParams.width = (textSize * 3) / 2;
            layoutParams.height = (textSize * 3) / 2;
            mDrawableRight.setLayoutParams(layoutParams);

            attributeArray.recycle();
        }
    }
}

Esempio: come usare la vista sopra

Layout: activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <com.customeditdrawable.AppEditTextWithDrawable
        android:id="@+id/edt_search_emp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:c_e_d_drawableRightSVG="@drawable/ic_svg_search"
        app:c_e_d_hint="@string/hint_search_here"
        app:c_e_d_textColor="@color/text_color_dark_on_light_bg"
        app:c_e_d_textSize="@dimen/text_size_small" />
</LinearLayout> 

Attività: MainActivity.java

public class MainActivity extends AppCompatActivity {
    EditTextWithDrawable mEditTextWithDrawable;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mEditTextWithDrawable= (EditTextWithDrawable) findViewById(R.id.edt_search_emp);
    }
}

Risposta a Touch Events

Molte visualizzazioni personalizzate devono accettare l'interazione dell'utente sotto forma di eventi tattili. Puoi accedere agli eventi touch ignorando onTouchEvent . Ci sono un certo numero di azioni che puoi filtrare. I principali sono

  • ACTION_DOWN : viene attivato una volta quando il dito tocca per la prima volta la vista.
  • ACTION_MOVE : viene chiamato ogni volta che il dito si sposta leggermente sulla vista. Viene chiamato molte volte.
  • ACTION_UP : questa è l'ultima azione da chiamare quando si solleva il dito dallo schermo.

È possibile aggiungere il seguente metodo alla vista e osservare l'output del registro quando si tocca e si sposta il dito sulla vista.

@Override
public boolean onTouchEvent(MotionEvent event) {

    int x = (int) event.getX();
    int y = (int) event.getY();
    int action = event.getAction();

    switch (action) {
        case MotionEvent.ACTION_DOWN:
            Log.i("CustomView", "onTouchEvent: ACTION_DOWN: x = " + x + ", y = " + y);
            break;

        case MotionEvent.ACTION_MOVE:
            Log.i("CustomView", "onTouchEvent: ACTION_MOVE: x = " + x + ", y = " + y);
            break;

        case MotionEvent.ACTION_UP:
            Log.i("CustomView", "onTouchEvent: ACTION_UP: x = " + x + ", y = " + y);
            break;
    }
    return true;
}

Ulteriori letture:



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow