In eigene View XML anhängen

D

diehard

Neues Mitglied
0
Hallo zusammen. Ich habe da ein kleines Problem. Ich habe die Activity:

Code:
public class Graphic extends Activity{
      ....

    
    /** Called when the activity is first created. */    
    @Override
    public void onCreate(Bundle savedInstanceState) {        
        super.onCreate(savedInstanceState);
        drawView = new MyDrawableView(this);
        
        setContentView(drawView);
        //drawView.setBackgroundColor(color.white);  
        
    }

Des weiteren Habe ich meine eigene View mit:

Code:
    public class MyDrawableView extends View {
        public MyDrawableView(Context context) {
            super(context);
            c = new Canvas();
            init();
        }
.....

Nun zu meiner Frage. Wie erweitere ich die Instanz drawView um einen XML-Datei in der ein EditText ist. Mir geht es einfach darum, dass ich ja nicht in der Activity mein Layout lade sondern meine eigene View. Aber ich hab keine Ahnung wie ich diese um XML-Dateien erweitern(add) kann.

Danke euch im Voraus.
 
Unicate schrieb:
Ich verstehe das so, dass du in deine eigene View andere Views reinladen möchtest. Seh ich das Richtig?

Wen dem so ist darfst du nicht nur von View ableiten, sondern kannst gleich von ViewGroup ableiten.

Was man dabei zu beachten hat findest du bei google.

Hier mal ein Beispiel was die evtl hilft:

Re: How to implement a custom layout, not extending existing one - Romain Guy - com.googlegroups.android-developers - MarkMail

Eigentlich nicht. Die Klasse public class MyDrawableView extends View beschreibt meine View. Die ich in der Activity mit der Instanz und dem Default-Konstrutor ertelle:

public class Graphic extends Activity{
private MyDrawableView drawView;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
drawView = new MyDrawableView(this);

setContentView(drawView)


Kann ich denn nicht einfach in der Klasse MyDrawableView extends View eine Konstruktor erstellen z.B:
public MyDrawableView(Context context, AttributeSet attributeSet){
super(context, attributeSet);
// TextEdit oder sonstige laden
}

Und dort meine XML-Datei laden? Das muss doch gehen. Oder geht das wirklich
nur über ViewGroup!
 
Achso, du willst einfach deine View aus einer XML laden.

Du musst einfach nur den Konstruktor mit den 2 Argumenten implementieren (im eclipse strg+s => "Generate Constructors from Superclass") und in deine XML deine View eintragen

<de.whatever.MeineTolleView android:id="@+id......." ... />

Hier ein beispiel meiner CheckableImageView:
Das ist die klasse:
PHP:
public class CheckableImageView extends ImageView implements Checkable {
    /**
     * The checkbox state
     */
    private boolean _checked = false;
    /**
     * if the checkbox is enabled at all
     */
    private boolean _enabled = true;
    /**
     * static Bitmap for the "checked" state
     * it's static because it just needs to be once
     * in the memory
     */
    private static Bitmap _bitmapChecked;
    private static Bitmap _bitmapUnchecked;
    
    /**
     * The OnCheckedChangeListener gets called when the
     * image was clicked 
     */
    private OnCheckedChangeListener _listener;
    
    /**
     * contructor
     * @param context The current context
     * @param attrs Attributes
     * @param defStyle styles
     */
    public CheckableImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }
    /**
     * constructor
     *  THIS IS THE ONE YOU NEED FOR THE XML
     * @param context The current Context
     * @param attrs Attributes
     */
    public CheckableImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    /**
     * The current context
     * @param context
     */
    public CheckableImageView(Context context) {
        super(context);
        init();
    }
    
    /**
     * The init method loads the Bitmaps into the memory
     * they will be loaded only once ('cause static)
     */
    public void init() {
        // one time load
        if(_bitmapChecked == null && _bitmapUnchecked == null) {
            _bitmapChecked = BitmapFactory.decodeResource(getResources(), R.drawable.field_checked);
            _bitmapUnchecked = BitmapFactory.decodeResource(getResources(), R.drawable.field_emtpy);
        }
    }
    
    /**
     * To set the OnCheckedChangeListener
     * 
     * @param listener OnCheckedChangeListener to set
     */
    public void setOnCheckedChangedListener(OnCheckedChangeListener listener) {
        _listener = listener;
    }
    
    /**
     * draw the view 
     */
    @Override
    protected void onDraw(Canvas canvas) {
        // draw the image
        super.onDraw(canvas);
        // if the checkboxes are enabled
        if(_enabled) {
            Bitmap bitmap = (_checked)?_bitmapChecked:_bitmapUnchecked;
            canvas.drawBitmap(bitmap, 5,5,new Paint());
        }
    }

    /**
     * From Interface Checkable implemented
     * method isChecked returns if the image 
     * is checked or not
     */
    @Override
    public boolean isChecked() {
        return _checked;
    }

    /**
     * From Interface Checkable implemented
     * method setChecked sets the image as checked
     * depending on the argument
     */
    @Override
    public void setChecked(boolean checked) {
        if(_checked != checked && null != _listener) {
            _listener.onCheckedChange(checked);
        }
        _checked = checked;
    }

    @Override
    /**
     * If the user clicks on the image 
     */
    public boolean performClick() {
        // toggle the checkbox
        toggle();
        // tell the view to redraw
        invalidate();
        return super.performClick();
    }
    @Override
    /**
     * toggles the checkbox
     */
    public void toggle() {
        _checked = !_checked;
        if(null != _listener)
            _listener.onCheckedChange(_checked);
    }
    
    /**
     * enables the checkbox depending on the argument
     */
    @Override
    public void setEnabled(boolean enabled) {
        _enabled = enabled;
        super.setEnabled(enabled);
    }
}
und hier die xml:

Code:
<?xml version="1.0" encoding="utf-8"?>
<de.unicate.customviews.CheckableImageView 
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/image"
        android:layout_width="wrap_content" 
        android:gravity="center_horizontal" 
        android:layout_height="wrap_content"
        android:layout_weight="2" />
 
Zuletzt bearbeitet:
@Unicat

Ok das ist auf jeden fall der richtige Ansatz. Wenn ich die XML definiert habe und den Konstruktor, wird trotz allem die XML nicht dargestellt. Aber korrekt interpretiert.

Angenommen ich möchte zu meiner eigenen View ... Buttons, EditText etc. hinzufügen. Zum einen mach ich das in der XML. Aber anscheinend reicht das nicht.
 
Naja, wenn du jetzt andere Elemente hinzufügen möchtest, kannst du diese einfach in die XML schreiben.

Poste doch mal den code, den du hast.
 
Unicate schrieb:
Naja, wenn du jetzt andere Elemente hinzufügen möchtest, kannst du diese einfach in die XML schreiben.

Poste doch mal den code, den du hast.

Also ich habe das nun versucht. Meine XML sieht dann so aus:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#888" android:layout_height="fill_parent"
android:layout_width="fill_parent" android:padding="30dip"
android:orientation="horizontal">
<Button android:id="@+id/continue_button" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="@string/continue_label" />
<de.android.crossword.MyDrawableView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/image"
android:layout_width="wrap_content"
android:gravity="center_horizontal"
android:layout_height="wrap_content"
android:layout_weight="2"
android:background="#666">
</de.android.crossword.MyDrawableView>
</LinearLayout>

In Eclipse kann ich mir ja das Layout anzeigen lassen und es sieht auch genau so aus wie in der XML beschrieben. Keine Fehler. Soweit so gut. Aber im Programm selber wird später nichts dargestellt?! Warum. Ich habe mal den Button anschließend in die XML so eingefügt:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#888" android:layout_height="fill_parent"
android:layout_width="fill_parent" android:padding="30dip"
android:orientation="horizontal">

<de.android.crossword.MyDrawableView

xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/image"
android:layout_width="wrap_content"
android:gravity="center_horizontal"
android:layout_height="wrap_content"
android:layout_weight="2"
android:background="#666">
<Button android:id="@+id/continue_button" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="@string/continue_label" />
</de.android.crossword.MyDrawableView>
</LinearLayout>

Dann bekomme ich die Meldung:

ClassCastExeption de....MyBeispieView cannot be cast to android.view.ViewGroup


EDIT: Was ich TOTAL übersehen hatte. Ich muss ja nicht den Konstruktor mit Context als Parameter aufrufen, sondern den mit 2 Parametern für context und attributes. Das mach ich in der onCreate-Methode. Aber was gebe ich für Attributes an. Siehe Code unten. Danke :)

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// KONSTRUKTOR RICHTIG AUFRUFEN
drawView = new MyDrawableView(this, ??? Attributes ???);
setContentView(drawView);
//drawView.setBackgroundColor(color.white);

}
 
Zuletzt bearbeitet:
Kann keiner weiter helfen?
 
Du musst deine eigene View nicht extra instanziieren. Sie wird automatisch instanziiert, wenn du die xml mit setContentView(R.layout.yourxml.xml); aufrufst.

Wenn du die werte darin verändern möchtest musst du die Elemente einzeln laden ((TextView)findViewById(R.id.mytextview)).setText("Hier steht mein text");
 
Unicate schrieb:
Du musst deine eigene View nicht extra instanziieren. Sie wird automatisch instanziiert, wenn du die xml mit setContentView(R.layout.yourxml.xml); aufrufst.

Wenn du die werte darin verändern möchtest musst du die Elemente einzeln laden ((TextView)findViewById(R.id.mytextview)).setText("Hier steht mein text");

Also ich rede mal Klartext :biggrin: was ich eigentlich vor habe. In erster Linie bekomme ich eine Fehlermeldung wenn ich das wie oben von dir beschrieben mache. In meiner Klasse Graphic die von View erbt, überschreibe ich die onDraw-Methode und zeichne ein Raster. Des weiteren werden noch einige andere Dinge in onDraw() gemacht welche die Oberfläche des Spielfeldes ausmachen. Nun muss ich nur noch einen EditText einbauen der so groß wie das Display ist und "hinter dem Raster ist bzw. invisible", aber trotzdem den focus behält, damit beim berühren des Display das SoftKeyboard auftaucht und ich viea TextWatcher die Eingabe abfangen kann. Mehr will ich aus der XML nicht raußholen, bzw. würde auch diesen EditText selbst implementieren da es ja mit der XML in meinen Augen für Probleme sorgt. Oder hast grad ein Bsp. parat wo in einer custom xml ein edittext etc. enthalten ist.
 
Ich glaube nicht das man ein EditText in den "Hintergrund" stellen kann, welches zusätzlich noch den Focus behält, also berichtigt mich wenn ich falsch liege, aber ich glaube das man das nur mit einer custom view machen kann.

Wenn du ein Spielfeld zeichnest nehm ich mal an, dass Du das für ein Spiel brauchst. wieso nimmst du kein SurfaceView dazu?

Wenn du eine EditText (oder was auch immer) hinter einer eigenen View verstecken möchtest, dann nimm ein AbsoluteLayout und gib dein EditText als erstes an, welches dann von deiner eigenen View überzeichnet wird. Den Focus wird es dabei aber nicht erhalten (evtl. kann man da mit irgend nem dunkeln hack den Focus auch aufrecht erhalten) aber für ein Spiel ist das mal ne düstere Steuerung.
Wenn es sich hier um ein Spiel handelt, empfehle ich die SurfaceView (Spieletutorial auf androidpit.de) und die touches des spielers abzufangen bzw. die tastatureingaben (fänd ich nicht so gut, da nicht alle devices eine tastatur haben bzw. das SoftKeyboard sich nicht zum Spielen eignet)

Wenn du aber einfach nur ein EditText mit anderen Bildchen haben möchtest (also wenn das anders aussehen soll) dann kannst du das einfach entweder von EditText ableiten und die onDraw methode überschreiben oder dem EditText ein neues aussehen verpassen. (Da gibt es auch Tutorials, hab sowas zumindest schon mal gesehen.)


Und die Klasse o.a. funktioniert 1a in meinem Projekt. (Wird von einem Adapter reigeladen, welcher ein GridView füllt.)
 
Zuletzt bearbeitet:
Unicate schrieb:
Ich glaube nicht das man ein EditText in den "Hintergrund" stellen kann, welches zusätzlich noch den Focus behält, also berichtigt mich wenn ich falsch liege, aber ich glaube das man das nur mit einer custom view machen kann.

Wenn du ein Spielfeld zeichnest nehm ich mal an, dass Du das für ein Spiel brauchst. wieso nimmst du kein SurfaceView dazu?

Wenn du eine EditText (oder was auch immer) hinter einer eigenen View verstecken möchtest, dann nimm ein AbsoluteLayout und gib dein EditText als erstes an, welches dann von deiner eigenen View überzeichnet wird. Den Focus wird es dabei aber nicht erhalten (evtl. kann man da mit irgend nem dunkeln hack den Focus auch aufrecht erhalten) aber für ein Spiel ist das mal ne düstere Steuerung.
Wenn es sich hier um ein Spiel handelt, empfehle ich die SurfaceView (Spieletutorial auf androidpit.de) und die touches des spielers abzufangen bzw. die tastatureingaben (fänd ich nicht so gut, da nicht alle devices eine tastatur haben bzw. das SoftKeyboard sich nicht zum Spielen eignet)

Wenn du aber einfach nur ein EditText mit anderen Bildchen haben möchtest (also wenn das anders aussehen soll) dann kannst du das einfach entweder von EditText ableiten und die onDraw methode überschreiben oder dem EditText ein neues aussehen verpassen. (Da gibt es auch Tutorials, hab sowas zumindest schon mal gesehen.)


Und die Klasse o.a. funktioniert 1a in meinem Projekt. (Wird von einem Adapter reigeladen, welcher ein GridView füllt.)

Darum geht es mir ja die ganze Zeit. Eigene View :) Leider ist mein Spiel ohne ein SoftKeyboard unmöglich....nennt sich Kreuzworträtsel :) Ich meine es Funktioniert wirklich alles. Ich ruf auch ein Softkeyboard auf aber kann die Eingabe ohne ein EditText nicht so ohne abfangen. Ich muss doch irgendwie einfach einen EditText in den Hintergrund bekommen. DAS MUSS GEHEN :)

Hier mein Code stark verkürzt:

Code:
package de.android.crossword;

//import com.example.android.apis.graphics.FingerPaint.MyView;

import java.io.IOException;

import java.util.Vector;

import org.xmlpull.v1.XmlPullParser;

import android.R.color;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Xml;
import android.view.Display;
import android.view.KeyEvent;
import android.view.View;
import android.view.MotionEvent;
import android.view.View.OnKeyListener;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.webkit.WebView;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import de.android.crossword.Logic_;
import de.android.crossword.LatinKeyboard;
import de.android.crossword.SoftKeyboard;

public class Graphic extends Activity{
      private boolean a = false;
    private MyDrawableView drawView;
    Logic_ logic;
    LatinKeyboard latinKeyboard;
    SoftKeyboard keyboard;
    
    
    /** Called when the activity is first created. */    
    @Override
    public void onCreate(Bundle savedInstanceState) {        
        super.onCreate(savedInstanceState);
        // KONSTRUKTOR RICHTIG AUFRUFEN
        Resources r = getResources();
        XmlPullParser parser = r.getXml(R.layout.main);
        AttributeSet attributes = Xml.asAttributeSet(parser);
        drawView = new MyDrawableView(this, attributes);
        setContentView(drawView);
        //drawView.setBackgroundColor(color.white);  
        
    }

    public class MyDrawableView extends View {
        
        final int ARRAYSIZEX = 35;
        final int ARRAYSIZEY = 25;
        final char SPACER = '|';
        Cell[][] array = new Cell[ARRAYSIZEX][ARRAYSIZEY];
        private EditText editText;
        
        private final int cell_size = 16;
        private int _height = 800;
        private int _width = 480;    
        private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        private boolean drawHorizontal = false;
        boolean actionFirstTime = false;
        boolean drawVertical = false;
        private float mCurX = 0;
        private float mCurY = 0;
      
        Canvas c;
        Paint paintRaster;
        Paint paintSelect;
        Paint paintSelectLine;
        Paint paintBackground;
        EditText mSkill;

        
        public MyDrawableView(Context context) {
            super(context);
            c = new Canvas();
            View newButton = findViewById(R.id.new_button);
            

            init();
        }
        
        public MyDrawableView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
        
         /*
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            _height = View.MeasureSpec.getSize(heightMeasureSpec);
            _width = View.MeasureSpec.getSize(widthMeasureSpec);
         
            setMeasuredDimension(_width, _height);
           
        }
        */
        
        private void init(){
             paint.setStyle(Paint.Style.STROKE);
             paint.setStrokeWidth(3);
             paint.setColor(Color.WHITE);
                       
             paintRaster = new Paint();
              paintRaster.setColor(Color.BLACK);
              paintRaster.setStyle(Paint.Style.STROKE);
              paintRaster.setStrokeWidth(2);
              paintSelect = new Paint();
              paintSelect.setColor(Color.argb(120, 0, 0, 255));
              paintSelect.setStyle(Paint.Style.STROKE);
              paintSelect.setStrokeWidth(1);
              paintSelect.setStyle(Style.FILL);
             
              paintSelectLine = new Paint();
              paintSelectLine.setColor(Color.argb(40, 0, 0, 255));
              paintSelectLine.setStyle(Paint.Style.STROKE);
              paintSelectLine.setStrokeWidth(1);
              paintSelectLine.setStyle(Style.FILL);
             
              paintBackground = new Paint();
              paintBackground.setColor(Color.argb(255, 255, 255, 255));
              paintBackground.setStyle(Paint.Style.STROKE);
              paintBackground.setStrokeWidth(1);
              paintBackground.setStyle(Style.FILL);
             setFocusable(true);
            }
        
  
        @Override
        public boolean onKeyDown (int keyCode, KeyEvent event){
            if(KeyEvent.KEYCODE_A == keyCode){
                a = true;
                invalidate();
                return super.onKeyDown(keyCode, event);
            }
            return true;
        }
        
        @Override
        public boolean onKeyUp(int keyCode, KeyEvent event){
            
            if(KeyEvent.KEYCODE_A == keyCode && event.getAction() == KeyEvent.ACTION_DOWN){
                a = true;
                return true;
            }
            return super.onKeyUp(keyCode, event);

        }
        
        @Override
        public boolean onTouchEvent(MotionEvent event){              
            int action = event.getAction();
            KeyEvent ev;
            
            if((action == MotionEvent.ACTION_DOWN) && (KeyEvent.FLAG_VIRTUAL_HARD_KEY != 0)){
                //Def. eines Eingabemanagers für die Tastatur
                InputMethodManager imm = (InputMethodManager)
                Graphic.this.getSystemService(Context.INPUT_METHOD_SERVICE);
                //latinKeyboard = new LatinKeyboard(keyboard, R.xml.qwerty);
        
                //Falls das Display berührt wird, wird die Virtuelle Tastatur geöffnet
                if (imm != null){
                    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED,0);
                }
                
                drawHorizontal = true;
                drawVertical = false;
                mCurX = (int)event.getX();
                mCurY = (int)event.getY();
                float bResX = mCurX%16;
                mCurX -= (bResX-8);
                float bResY = mCurY%16;
                mCurY -= (bResY-8);
                invalidate();                
                
                if(action == MotionEvent.ACTION_DOWN && actionFirstTime == true){
                    drawVertical = true;
                    actionFirstTime = false;
                    drawHorizontal = false;
                }else{
                    actionFirstTime = true;
                }
            }
            return true;
        }
           
        
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            // HIER ZEICHNE ICH MEIN SPIEL
        }
    }
}
 
Ok, bei nem Kreuzworträtsel macht ein Keyboard natürlich Sinn :D.

Mh...

Wie wärs mit nem Dialog Fenster, in dem du ein Wort eingeben kannst?

Also der User klickt auf eine Im Kreuzworträtsel gestellte frage und es öffnet sich ein Dialogfenster wo er sein Lösungswort einträgt.
Für ne direkte Lösung habe ich keine Idee.
 
  • Danke
Reaktionen: diehard
Unicate schrieb:
Ok, bei nem Kreuzworträtsel macht ein Keyboard natürlich Sinn :D.

Mh...

Wie wärs mit nem Dialog Fenster, in dem du ein Wort eingeben kannst?

Also der User klickt auf eine Im Kreuzworträtsel gestellte frage und es öffnet sich ein Dialogfenster wo er sein Lösungswort einträgt.
Für ne direkte Lösung habe ich keine Idee.

Erstmal bedanke ich mich bei dir. Du bist immerhin der "einzige" aus einem Forum der mir geholfen hat. Des weiteren war das mit dem Dialogfenster meine erste banale Idee. Finde ich aber nicht erwartungskonform und ergonomisch genug. Man möchte eigentlich nur einen Buchstaben in ein Feld eintragen. Aber da das Programm eh nicht für mich ist werde ich glaub diesen einfachen weg einschlagen :) Ich melde mich bei Problemen. Hab da echt keine Lust mehr drauf zudem ich eine Grippe habe und bis Sonntag es fertig haben muss.
 

Ähnliche Themen

FabianDev
Antworten
5
Aufrufe
547
swa00
swa00
F
  • Fischi84
Antworten
2
Aufrufe
1.914
Fischi84
F
R
Antworten
3
Aufrufe
1.612
Ritartet
R
Zurück
Oben Unten