2016-02-21 2 views
0

Je voudrais avoir un carré (même largeur que la hauteur) GridView remplir toute la hauteur de l'écran en orientation paysage. Le Gridview est un échiquier (8 par 8 carrés) avec le xml:Élément carré pleine hauteur en android

<com.example.jens.jchess2.view.MyGridView 
    android:id="@+id/chessboard" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:padding="0dp" 
    android:numColumns="8" 
    android:verticalSpacing="0dp" 
    android:horizontalSpacing="0dp"> 
</com.example.jens.jchess2.view.MyGridView> 

et les éléments de la grille sont:

<?xml version="1.0" encoding="utf-8"?> 
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/square" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:background="#000080" 
    android:orientation="vertical" 
    android:padding="0pt"> 

    <ImageView 
     android:id="@+id/square_background" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:adjustViewBounds="true" 
     android:padding="0pt" /> 


    <ImageView 
     android:id="@+id/piece" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_gravity="center" 
     android:adjustViewBounds="true" 
     android:padding="0pt" /> 

</FrameLayout> 

, où les ImageViews correspondent à des carrés et des pièces (tous deux de images png) du tableau.

Dans la coutume MyGridView je passer outre onMeasure comme suit:

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    int width = MeasureSpec.getSize(widthMeasureSpec); 
    int height = getContext().getResources().getDisplayMetrics().heightPixels; 


    if (width > height) { 
     super.onMeasure(
       MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY), 
       MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY) 
     ); 
    } else { 
     super.onMeasure(
       MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), 
       MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY) 
     ); 
    } 
} 

qui me donne un GridView carré portrait et paysage orientation. En mode portrait, il remplit toute la largeur et tout va bien. En mode paysage, cependant, il s'étend en dessous de l'écran parce que la hauteur (= largeur) du GridView/board est trop grande. Il est trop grand par la hauteur de la barre d'outils et la hauteur de la barre d'état. Comment puis-je obtenir la bonne taille pour le GridView, c'est-à-dire la hauteur de l'écran moins la hauteur de la barre d'état moins la hauteur de la barre d'outils?

+0

rendre heightMeasureSpec égal à la hauteur de la fenêtre .... –

Répondre

0

Commencez avec deux versions de votre fichier de mise en page:

/res/layout/grid.xml

... 

    <!-- full width --> 
    <com.example.MyGridView 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     ... 
     /> 

    ... 

/res/layout-land/grid.xml

... 

    <!-- full height --> 
    <com.example.MyGridView 
     android:layout_width="wrap_content" 
     android:layout_height="match_parent" 
     ... 
     /> 

    ... 

Vous probablement déjà quelque chose comme ça.

Maintenant dans votre onMeasure() prioritaire, la dimension match_parent aura un mode MeasureSpec de EXACTLY et la dimension wrap_content aura un mode MeasureSpec de AT_MOST. Vous pouvez l'utiliser pour obtenir la disposition souhaitée.

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 

    int width = MeasureSpec.getSize(widthMeasureSpec); 
    int height = MeasureSpec.getSize(heightMeasureSpec); 
    int widthMode = MeasureSpec.getMode(widthMeasureSpec); 
    int heightMode = MeasureSpec.getMode(heightMeasureSpec); 


    if (widthMode == MeasureSpec.EXACTLY && heightMode == MeasureSpec.AT_MOST) { 
     // portrait 
     super.onMeasure(widthMeasureSpec, widthMeasureSpec); 

    } else if (heightMode == MeasureSpec.EXACTLY && widthMode == MeasureSpec.AT_MOST) { 
     // landscape 
     super.onMeasure(heightMeasureSpec, heightMeasureSpec); 

    } else { 
     super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
    } 
} 

EDIT: Je trouve que les deux modes peuvent être en fonction AT_MOST sur le récipient ViewGroup. S'il vous plaît voir mon autre réponse pour le code de mesure mis à jour.

+0

Cela ne semble pas fonctionner pour moi. Je n'ai qu'une seule rangée d'éléments de la grille. – user1583209

+0

Le 'GridView' est-il carré? Si tel est le cas, vous devrez peut-être faire quelque chose pour que vos vues d'objet soient redimensionnées différemment. Si vous pouviez publier votre mise en page d'éléments de grille XML, cela aiderait. –

+0

Merci pour la réponse, j'ai posté le XML des éléments de la grille ci-dessus et a également essayé de clarifier quel est mon problème. – user1583209

0

Ah. Maintenant, je vois que c'est pour un jeu.

Il est parfois préférable d'avoir des mises en page et des vues enfant, mais dans la plupart des cas avec des plateaux de jeu, il vaut mieux créer une seule sous-classe View qui représente la vue du jeu. Par exemple, que se passe-t-il si vos utilisateurs disent qu'ils veulent pouvoir zoomer dans un quadrant du plateau de jeu? Vous ne pouvez pas faire cela avec un GridView.

J'ai créé une application simple pour vous montrer comment cela peut fonctionner. J'ai simplifié le code onMeasure() que j'avais posté auparavant, et au lieu d'un GridView, une seule sous-classe View restitue le plateau de jeu. MainActivity configure simplement l'affichage du contenu.

/res/layout/activité_main.xml:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:paddingBottom="@dimen/activity_vertical_margin" 
    android:paddingLeft="@dimen/activity_horizontal_margin" 
    android:paddingRight="@dimen/activity_horizontal_margin" 
    android:paddingTop="@dimen/activity_vertical_margin" 
    tools:context="com.example.gameboard.MainActivity"> 

    <com.example.gameboard.GameBoardView 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" /> 
</RelativeLayout> 

/res/layout-land/activity_main.xml:

Avis match_parent et wrap_content sont commutées pour la largeur et la hauteur.

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:paddingBottom="@dimen/activity_vertical_margin" 
    android:paddingLeft="@dimen/activity_horizontal_margin" 
    android:paddingRight="@dimen/activity_horizontal_margin" 
    android:paddingTop="@dimen/activity_vertical_margin" 
    tools:context="com.example.gameboard.MainActivity"> 

    <com.example.gameboard.GameBoardView 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_centerHorizontal="true" /> 
</RelativeLayout> 

GameBoardView.java:

public class GameBoardView extends View { 

    private Paint mPaint; 

    public GameBoardView(Context context) { 
     super(context); 
    } 

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

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

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

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 

     int width = MeasureSpec.getSize(widthMeasureSpec); 
     int height = MeasureSpec.getSize(heightMeasureSpec); 
     int size = Math.min(width, height); 
     int sizeMeasureSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY); 

     super.onMeasure(sizeMeasureSpec, sizeMeasureSpec); 

     mPaint = new Paint(); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 

     int w = getWidth()/8; 
     int h = getHeight()/8; 

     for (int row = 0; row < 8; row++) { 
      for (int col = 0; col < 8; col++) { 
       // choose black or white depending on the square 
       mPaint.setColor((row + col) % 2 == 0 ? 0xFFFFFFFF : 0xFF000000); 
       canvas.drawRect(w * col, h * row, w * (col + 1), h * (row + 1), mPaint); 
      } 
     } 
    } 
} 

Ici je dessine juste les places en plein la vue. Maintenant, si je faisais un jeu d'échecs, je créerais également une sous-classe Drawable qui prendrait le modèle de jeu et le rendrait. Avoir un Drawable séparé pour rendre le jeu le rend facile à l'échelle à la bonne taille. Par exemple, votre Drawable peut rendre à une taille constante fixe, puis être mis à l'échelle par la sous-classe View pour s'adapter. La sous-classe View fonctionnerait principalement comme un contrôleur, interprétant les événements tactiles et mettant à jour le modèle de jeu.