Suche…


Benutzerdefinierte Ansichten erstellen

Wenn Sie eine vollständig angepasste Ansicht benötigen, müssen Sie die Ansicht " View (die Oberklasse aller Android-Ansichten) unterteilen und Ihre benutzerdefinierten onMeasure(...) ) und Zeichnungsmethoden ( onDraw(...) ) onDraw(...) :

  1. Erstellen Sie Ihr benutzerdefiniertes Ansichtskelett: Dies ist grundsätzlich für jede benutzerdefinierte Ansicht gleich. Hier erstellen wir das Skelett für eine benutzerdefinierte Ansicht, die einen Smiley namens 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. Initialisieren Sie Ihre Farben: Die Paint Objekte sind die Pinsel Ihrer virtuellen Leinwand, die festlegen, wie Ihre geometrischen Objekte (z. B. Farbe, Füll- und Konturenstil usw.) gerendert werden. Hier erstellen wir zwei Paint , eine gelbe Farbe für den Kreis und eine schwarze Strichfarbe für Augen und Mund:

    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. Implementieren Sie Ihre eigene onMeasure(...) -Methode: Dies ist erforderlich, damit die übergeordneten Layouts (z. B. FrameLayout ) Ihre benutzerdefinierte Ansicht richtig ausrichten können. Sie enthält eine Reihe von measureSpecs , mit deren Hilfe Sie Höhe und Breite Ihrer Ansicht bestimmen können. Hier erstellen wir ein Quadrat, indem wir sicherstellen, dass Höhe und Breite gleich sind:

    @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);
    }
    

    Beachten Sie, dass onMeasure(...) mindestens einen Aufruf von setMeasuredDimension(..) enthalten muss. setMeasuredDimension(..) Ihre benutzerdefinierte Ansicht mit einer IllegalStateException .

  4. Implementieren Sie Ihre eigene onSizeChanged(...) -Methode: Damit können Sie die aktuelle Höhe und Breite Ihrer benutzerdefinierten Ansicht abrufen, um Ihren Rendering-Code richtig anzupassen. Hier berechnen wir nur unser Zentrum und unseren Radius:

    @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. Implementieren Sie Ihre eigene onDraw(...) -Methode: Hier implementieren Sie das tatsächliche Rendern Ihrer Ansicht. Es stellt ein Canvas Objekt bereit, auf das Sie Canvas können (alle offiziellen Zeichenmethoden finden Sie in der offiziellen Canvas Dokumentation).

    @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. Fügen Sie Ihre benutzerdefinierte Ansicht einem Layout hinzu: Die benutzerdefinierte Ansicht kann jetzt in alle vorhandenen Layoutdateien eingefügt werden. Hier wickeln wir es einfach in ein 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>
    

Beachten Sie, dass es empfohlen wird, Ihr Projekt zu erstellen, nachdem der Ansichtscode abgeschlossen ist. Ohne sie zu erstellen, können Sie die Ansicht auf einem Vorschaubildschirm in Android Studio nicht sehen.

Nachdem Sie alles zusammengestellt haben, sollten Sie nach dem Starten der Aktivität, die das obige Layout enthält, mit dem folgenden Bildschirm begrüßt werden:

SmileyView verwendet Aktivität im Inneren

Attribute zu Ansichten hinzufügen

Benutzerdefinierte Ansichten können auch benutzerdefinierte Attribute enthalten, die in Android-Layout-Ressourcendateien verwendet werden können. Um Ihrer benutzerdefinierten Ansicht Attribute hinzuzufügen, müssen Sie Folgendes tun:

  1. Definieren Sie den Namen und den Typ Ihrer Attribute: Dies geschieht in res/values/attrs.xml ( res/values/attrs.xml erstellen). Die folgende Datei definiert ein Farbattribut für die Gesichtsfarbe unseres Smileys und ein Aufzählungsattribut für den Ausdruck des Smileys:

    <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. Verwenden Sie Ihre Attribute in Ihrem Layout: Dies kann in allen Layoutdateien erfolgen, die Ihre benutzerdefinierte Ansicht verwenden. Die folgende Layoutdatei erstellt einen Bildschirm mit einem fröhlichen gelben Smiley:

    <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>
    

    Tipp: Benutzerdefinierte Attribute funktionieren nicht mit den tools: Präfix in Android Studio 2.1 und älter (und möglicherweise in zukünftigen Versionen). In diesem Beispiel wird app:smileyColor durch tools:smileyColor , smileyColor weder zur Laufzeit noch zur Entwurfszeit festgelegt wird.

  3. Lesen Sie Ihre Attribute: Dies geschieht in Ihrem benutzerdefinierten Ansichts-Quellcode. Der folgende Ausschnitt von SmileyView zeigt, wie die Attribute extrahiert werden können:

    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. (Optional) Standardstil hinzufügen : Dazu fügen Sie einen Stil mit den Standardwerten hinzu und laden ihn in Ihre benutzerdefinierte Ansicht. Der folgende Standard-Smiley-Stil steht für einen glücklichen gelben Stil:

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

    Welches wird in unserem SmileyView angewendet, indem es als letzter Parameter des Aufrufs von obtainStyledAttributes (siehe Code in Schritt 3):

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

    Beachten Sie, dass bei Attributwerten, die in der aufgeblähten Layoutdatei festgelegt wurden (siehe Code in Schritt 2), die entsprechenden Werte des Standardstils überschrieben werden.

  5. (Optional) Bereitstellen von Stilen in Designs: Dazu fügen Sie ein neues Stilreferenzattribut hinzu, das in Ihren Designs verwendet werden kann, und stellt einen Stil für dieses Attribut bereit. Hier nennen wir einfach unser Referenzattribut smileyStyle :

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

    Für das wir dann einen Stil in unserem App-Theme bereitstellen (hier verwenden wir einfach den Standardstil aus Schritt 4):

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

Zusammengesetzte Ansicht erstellen

Eine zusammengesetzte Ansicht ist eine benutzerdefinierte ViewGroup , die vom umgebenden Programmcode als einzelne Ansicht behandelt wird. Eine solche ViewGroup kann im DDD- ähnlichen Design sehr nützlich sein, da sie einem Aggregat, in diesem Beispiel einem Kontakt, entsprechen kann. Sie kann überall dort verwendet werden, wo der Kontakt angezeigt wird.

Dies bedeutet, dass der umgebende Controller-Code, eine Aktivität, ein Fragment oder ein Adapter, das Datenobjekt einfach an die Ansicht übergeben kann, ohne es in einer Reihe verschiedener UI-Widgets aufzuteilen.

Dies erleichtert die Wiederverwendung von Code und sorgt für ein besseres Design gemäß den SOLID-Grundsätzen .

Das Layout XML

Hier fängt man normalerweise an. Sie haben ein vorhandenes Stück XML, das Sie wiederverwenden können, möglicherweise als <include/> . Extrahieren Sie es in eine separate XML-Datei und umschließen Sie das Root-Tag in einem <merge> -Element:

<?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>

Diese XML-Datei funktioniert weiterhin einwandfrei im Layout-Editor von Android Studio. Sie können es wie jedes andere Layout behandeln.

Die zusammengesetzte ViewGroup

Wenn Sie die XML-Datei haben, erstellen Sie die benutzerdefinierte Ansichtsgruppe.

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);
        }
    }
}

Bei der init(Context, AttributeSet) Methode init(Context, AttributeSet) lesen Sie benutzerdefinierte XML-Attribute, wie unter Hinzufügen von Attributen zu Ansichten beschrieben .

Mit diesen Stücken können Sie sie in Ihrer App verwenden.

Verwendung in XML

Hier ein Beispiel für fragment_contact_info.xml , das veranschaulicht, wie Sie eine einzelne ContactView über eine Liste von Nachrichten setzen:

<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>

Verwendung im Code

Hier ist ein Beispiel für RecyclerView.Adapter , das eine Liste von Kontakten enthält. Dieses Beispiel zeigt, wie viel sauberer der Controller-Code wird, wenn er völlig frei von View-Manipulationen ist.

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
        }
    }
}

CustomView-Leistungstipps

Ordnen Sie keine neuen Objekte in onDraw zu

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

Anstatt Drawables auf Leinwand zu zeichnen ...

drawable.setBounds(boundsRect);

drawable.draw(canvas);

Verwenden Sie eine Bitmap zum schnelleren Zeichnen:

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

Zeichnen Sie nicht die gesamte Ansicht neu, um nur einen kleinen Teil der Ansicht zu aktualisieren. Zeichnen Sie stattdessen den bestimmten Teil der Ansicht neu.

invalidate(boundToBeRefreshed);

Wenn Ihre Ansicht eine kontinuierliche Animation tut, zum Beispiel eine Uhr-Gesicht jede Sekunde zeigt, zumindest stoppen Sie die Animation bei onStop() der Aktivität und starten Sie ihn wieder auf onStart() der Aktivität.

onDraw Sie keine Berechnungen innerhalb der onDraw Methode einer Ansicht durch. Stattdessen sollten Sie die Zeichnung beenden, bevor Sie onDraw invalidate() aufrufen. Mit dieser Technik können Sie verhindern, dass Bilder in Ihrer Ansicht verschoben werden.

Drehungen

Die grundlegenden Vorgänge einer Ansicht sind Übersetzen, Drehen usw. ... Fast jeder Entwickler ist mit diesem Problem konfrontiert, wenn er Bitmap oder Farbverläufe in seiner benutzerdefinierten Ansicht verwendet. Wenn in der Ansicht eine gedrehte Ansicht angezeigt wird und die Bitmap in dieser benutzerdefinierten Ansicht gedreht werden muss, glauben viele von uns, dass dies teuer wird. Viele denken, dass das Drehen einer Bitmap sehr teuer ist, weil dafür die Pixelmatrix der Bitmap übersetzt werden muss. Aber die Wahrheit ist, dass es nicht so schwer ist! Anstatt die Bitmap zu drehen, drehen Sie einfach die Leinwand selbst!

// 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.

Zusammengesetzte Ansicht für SVG / VectorDrawable als drawableRight

Hauptmotiv für die Entwicklung dieser zusammengesetzten Ansicht ist, dass unter 5.0 Geräte svg nicht in TextView / EditText drawable unterstützt. Ein weiteres drawableRight ist, wir können die height und width von drawableRight in EditText . Ich habe es von meinem Projekt getrennt und in einem separaten Modul erstellt.

Modulname: custom_edit_drawable (Kurzname für Präfix c_d_e)

Präfix "c_d_e_", damit die Ressourcen des App-Moduls nicht versehentlich überschrieben werden. Beispiel: Das Präfix "abc" wird von Google in der Support-Bibliothek verwendet.

build.gradle

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

Verwenden Sie AppCompat> = 23

Layoutdatei: 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>

Benutzerdefinierte Attribute: 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>

Code: 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();
        }
    }
}

Beispiel: Verwendung der obigen Ansicht

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> 

Tätigkeit: 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);
    }
}

Reagieren auf Berührungsereignisse

Viele benutzerdefinierte Ansichten müssen Benutzerinteraktionen in Form von Berührungsereignissen akzeptieren. Sie können Zugriff auf Berührungsereignisse erhalten, indem Sie onTouchEvent überschreiben. Es gibt eine Reihe von Aktionen, die Sie herausfiltern können. Die wichtigsten sind

  • ACTION_DOWN : Dies wird einmal ausgelöst, wenn Ihr Finger die Ansicht zum ersten Mal berührt.
  • ACTION_MOVE : Dies wird jedes Mal aufgerufen, wenn sich Ihr Finger ein wenig über die Ansicht bewegt. Es wird oft aufgerufen.
  • ACTION_UP : Dies ist die letzte Aktion, die aufgerufen wird, wenn Sie Ihren Finger vom Bildschirm nehmen.

Sie können Ihrer Ansicht die folgende Methode hinzufügen und dann die Protokollausgabe beobachten, wenn Sie Ihren Finger berühren und um Ihre Ansicht bewegen.

@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;
}

Lesen Sie weiter:



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow