1. Nimm jetzt an unserem 2. ADVENT-Gewinnspiel teil - Alle Informationen findest Du hier!

In eigene View XML anhängen

Dieses Thema im Forum "Android App Entwicklung" wurde erstellt von diehard, 07.03.2011.

  1. diehard, 07.03.2011 #1
    diehard

    diehard Threadstarter Neuer Benutzer

    Beiträge:
    11
    Erhaltene Danke:
    0
    Registriert seit:
    24.02.2011
    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.
     
  2. Unicate, 07.03.2011 #2
    Unicate

    Unicate Android-Experte

    Beiträge:
    473
    Erhaltene Danke:
    57
    Registriert seit:
    09.08.2010
    Zuletzt bearbeitet: 07.03.2011
  3. diehard, 07.03.2011 #3
    diehard

    diehard Threadstarter Neuer Benutzer

    Beiträge:
    11
    Erhaltene Danke:
    0
    Registriert seit:
    24.02.2011
    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!
     
  4. Unicate, 07.03.2011 #4
    Unicate

    Unicate Android-Experte

    Beiträge:
    473
    Erhaltene Danke:
    57
    Registriert seit:
    09.08.2010
    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 contextAttributeSet attrsint defStyle) {
            
    super(contextattrsdefStyle);
            
    init();
        }
        
    /**
         * constructor
         *  THIS IS THE ONE YOU NEED FOR THE XML
         * @param context The current Context
         * @param attrs Attributes
         */
        
    public CheckableImageView(Context contextAttributeSet attrs) {
            
    super(contextattrs);
            
    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(bitmap5,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: 07.03.2011
  5. diehard, 07.03.2011 #5
    diehard

    diehard Threadstarter Neuer Benutzer

    Beiträge:
    11
    Erhaltene Danke:
    0
    Registriert seit:
    24.02.2011
    @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.
     
  6. Unicate, 07.03.2011 #6
    Unicate

    Unicate Android-Experte

    Beiträge:
    473
    Erhaltene Danke:
    57
    Registriert seit:
    09.08.2010
    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.
     
  7. diehard, 08.03.2011 #7
    diehard

    diehard Threadstarter Neuer Benutzer

    Beiträge:
    11
    Erhaltene Danke:
    0
    Registriert seit:
    24.02.2011
    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: 08.03.2011
  8. diehard, 09.03.2011 #8
    diehard

    diehard Threadstarter Neuer Benutzer

    Beiträge:
    11
    Erhaltene Danke:
    0
    Registriert seit:
    24.02.2011
    Kann keiner weiter helfen?
     
  9. Unicate, 09.03.2011 #9
    Unicate

    Unicate Android-Experte

    Beiträge:
    473
    Erhaltene Danke:
    57
    Registriert seit:
    09.08.2010
    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");
     
  10. diehard, 09.03.2011 #10
    diehard

    diehard Threadstarter Neuer Benutzer

    Beiträge:
    11
    Erhaltene Danke:
    0
    Registriert seit:
    24.02.2011
    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.
     
  11. Unicate, 09.03.2011 #11
    Unicate

    Unicate Android-Experte

    Beiträge:
    473
    Erhaltene Danke:
    57
    Registriert seit:
    09.08.2010
    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: 09.03.2011
  12. diehard, 09.03.2011 #12
    diehard

    diehard Threadstarter Neuer Benutzer

    Beiträge:
    11
    Erhaltene Danke:
    0
    Registriert seit:
    24.02.2011
    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
            }
        }
    }
     
  13. Unicate, 09.03.2011 #13
    Unicate

    Unicate Android-Experte

    Beiträge:
    473
    Erhaltene Danke:
    57
    Registriert seit:
    09.08.2010
    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.
     
    diehard bedankt sich.
  14. diehard, 09.03.2011 #14
    diehard

    diehard Threadstarter Neuer Benutzer

    Beiträge:
    11
    Erhaltene Danke:
    0
    Registriert seit:
    24.02.2011
    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.
     

Diese Seite empfehlen