Telas Horizontais e verticais no android

44 respostas
V

Estou tendo dificuldade de como deixar a tela vertical da minha aplicação alinhada.
Eu tenho a aplicação na horizontal, e fica tudo certinho, bem alinhado, porém, quando eu coloco na vertical, a imagem do meio fica totalmente desalinhada.
É o seguinte, coloquei no diretorio drawable-hdpi a imagem back no formato horizontal, e no diretorio drawable-land a imagem back no formato vertical.
As duas com o mesmo nome. Até ai tudo certo.
Só que, ao colocar a imagem logo tb nos dois diretórios, quando vai pra vertical da problema
alguem pode me ajudar?

public void onDraw(Canvas canvas){
	      
		 
		   canvas.save();
		   canvas.drawBitmap(background, 0, 0, paint);
	           canvas.drawBitmap(logo, 110, 70, paint);
		   canvas.restore();
	   }

44 Respostas

Marky.Vasconcelos

Mas voce desenha tudo na mão?

Por que não usa os atributos android:background dos componentes para isso? Esses o Android resolve sozinhod e acordo com a orientação.

V

Estava desenhando sim utilizando canvas.
Então como é que fica?
Não sei desse jeito que vc está dizendo

V

Outra coisa,
o background vai ficar desse jeito que vc falou, e as imagens tb?
Fiquei sem entender.

V

Marky.Vasconcelos

Consegui fazer o background,
ficou assim, confere?

android:background="@drawable/back"

Tudo ok. no caso do restante das imagens?
Eu tenho um logo que é pra ficar no meio da tela, de acordo com meu codigo ele fica na vertical, porem na horizontal nao fica.

Marky.Vasconcelos

Posta seu XML.

V
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:background="@drawable/back"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
	
	<com.android.RedeDroidCanvas 
	 android:layout_width="fill_parent"
	 android:layout_height="fill_parent" 
	 android:id="@+id/RedeDroidCanvas">
	</com.android.RedeDroidCanvas>
	</LinearLayout>

no meu canvas consegui deixar a imagem no meio

canvas.drawBitmap(logo, (getWidth()/2) - (logo.getWidth()/2), (getHeight()/2) - (logo.getHeight()/2), paint);

Só não estou entendendo o seguinte,
Essa é minha tela inicial, deu certo.
ai no caso da tela de jogo mesmo que eu vou ter que colocar imagens mais a direita, ou a esquerda, como que vai ficar a questao do rendimensionamento da tela?

Marky.Vasconcelos

Ahh… isso é um jogo, ai a coisa muda.

Normalmente o que os devs fazem é criar o jogo para apenas uma orientação, o que na minha opnião é bem melhor do que se preocupar em ter um layout para os dois.

No seu caso, voce vai precisar verificar a orientação atual e pegar a imagem correta e desenhar no seu componente. O Android só cuida disso na hora que voce vai fazer o load das imagens enquanto inflando.

V

Marky,
Pode me explicar melhor?
Devs?

V

Marky ou alguém?

M

Vai ter que implementar transformação de matrizes, infelizmente não tem isso pronto no android.

Marky.Vasconcelos

Se voce está fazendo um jogo, por que quer suportar landscape e portrait? Isso te obriga a fazer um layout para cada orientação para aproveitar melhor o espaço.

M

No iOS basta configurar o componente para ocupar toda a tela e fazer:

componente.transform = CFAffineTransformMakeRotation(RADIANS(90));

Android tem que implementar tudo na mão. Não me leve a mal, os aparelhos podem ser fantásticos, mas em termos de API e ferramentas para o desenvolvedor, Android é mais parecido com j2me.

j0nny

Apenas lembrando, não alimente os trolls.

Marky.Vasconcelos

No iOS basta configurar o componente para ocupar toda a tela e fazer:

componente.transform = CFAffineTransformMakeRotation(RADIANS(90));

Android tem que implementar tudo na mão. Não me leve a mal, os aparelhos podem ser fantásticos, mas em termos de API e ferramentas para o desenvolvedor, Android é mais parecido com j2me.

Ta bom, e como voce vai especificar um layout para cada orientação apenas girando a tela?

Deixar apenas uma unica orientação na aplicação é tão facil no Android quanto no iOS.

M

Bom, não sei qual o jogo em questão, se é indicado ou não usar as duas orientaçoes, provavelmente vc esta certo. Mas…

…pello que entendi “é tão fácil quanto” quer dizer que não existe outra possiblidade a não ser usar um layout para cada tela ou então implementar seu proprio framework e por isso a comparação com j2me.

Marky.Vasconcelos

Para deixar apenas uma orientação no Android, basta invocar o seguinte na sua atividade.

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
V

Então vcs querem dizer que quando se trata de jogo, não é tão viável colocar das duas formas?

Marky, esse método faz o que?
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

Marky.Vasconcelos

Faz um request para ficar nessa orientação.

E quando é jogos, não faz muito sentido manter as duas orientações, já que voce pode fazer o layout para aproveitar bem mais um tamanho especifico.

V

Ok.

Aproveitando a situação, gostaria que vcs me ajudassem em outra coisa.
Eu gostaria de fazer uma tela que quando abrisse o jogo aparecesse o logo e dpois fosse pro menu, uma espécie de Splash Window.
No caso, eu implemento o método run na classe que desenha as imagens ou na classe principal que chama as outras?

Eis as classes.

package com.android;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ProgressBar;


public class RedeDroidCanvas extends View{
	  private Bitmap logo;
	  private Paint paint;
	  
	
	
	   public RedeDroidCanvas(Context context) {
	      super(context);
	      init();
	   }
	   public RedeDroidCanvas(Context context, AttributeSet attrs) {
	      super(context, attrs);
	      init();
	   }
	   public RedeDroidCanvas(Context context, AttributeSet attrs, int defStyle) {
	      super(context, attrs, defStyle);
	      init();
	   }
	   private void init() {
		   logo = BitmapFactory.decodeResource(getResources(), R.drawable.logo);
		   paint = new Paint();
	   }
	   public void onDraw(Canvas canvas){
	           canvas.save();
		   canvas.drawBitmap(logo, (getWidth()/2) - (logo.getWidth()/2), (getHeight()/2) - (logo.getHeight()/2), paint);
		   canvas.restore();
	   }

	   
	

}
public class RedeDroid extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
       
    } 
}
V

Também já havia esquecido,
Como que eu faço para clicar em uma imagem feita em canvas?

Marky.Vasconcelos

vasco.fred:
Também já havia esquecido,
Como que eu faço para clicar em uma imagem feita em canvas?

Voce vai ter que fazer isso programaticamente, saber onde os objetos desenhados estão e traduzir o clique no canvas para saber qual imagem é.

Luiz_Aguiar

Dependendo do jogo, fica “injogável” essa mudança de orientação, precisa analisar bem isso, se existe realmente essa necessidade ou se é apenas para ter a “funcionalidade”.

[]s

V

Ok Marky.

Vou tentar aqui, mas, aproveitando =) tem algum código de exemplo?
Outra coisa, os jogos que vemos em android hj em dia é criado com canvas?
Posso mt bem criar um jogo em canvas e vender?

Marky.Vasconcelos

Pode sim. É possivel criar totalmente no Canvas.

Como também é possivel usar aceleração nativa com OpenGL ES

V

Agora eu não entendo como que eu vou fazer para que o android entenda, pq tipo, o canvas não é um botão, com isso, não posso criar o setOnClickListener ;
Alguma sugestão?

menuNovoJogo = BitmapFactory.decodeResource(res,R.drawable.novojogo);

menuNovoJogo.setOnClickListener(new View.OnClickListener() {
			
			public void onClick(View v) {
	
				
			}
		});

E se eu o criar como um ImageButton, tb da problema

Imagebutton = (ImageButton) findViewById(R.drawable.novojogo);

public void onDraw(Canvas canvas){

		   button.draw(canvas);
}
Marky.Vasconcelos

Voce pode implementar o onTouchListener para sua View, e não para o Bitmap.

Mas voce ainda vai ter que pegar o x,y e descobrir em qual componente o usuario esta tocando.

V

Ok,
mas existe alguma outra maneira?
Pq eu fiz isso e nao deu mt certo.
Estou testando primeiro pra conseguir clicar na tela e fazer algo

float posX = 200;
public void onDraw(Canvas canvas){
	  
		   canvas.drawBitmap(menuNovoJogo, posX, 100, paint);
}

public boolean onTouch(View v, MotionEvent event) {
		switch(event.getAction()){
			case MotionEvent.ACTION_DOWN:{
				posX = event.getX();
				break;
			}
		}
		
		return true;
	}
V

E então,
alguem sabe me dizer como fazer com que eu possa deixar um bitmap como um botão?

Tentei utilizar um imageButton, porém, ele nao desenha com canvas.

Alguém pode me dar uma luz a respeito?

Marky.Vasconcelos
float posX = 200;
public void onDraw(Canvas canvas){
	  
		   canvas.drawBitmap(menuNovoJogo, posX, 100, paint);
}

public boolean onTouch(View v, MotionEvent event) {
		switch(event.getAction()){
			case MotionEvent.ACTION_DOWN:{
                               if(event.getX() > posX && event.getX() < posX + imagem.getWidth()){ //Clicou na area da imagem }
				break;
			}
		}
	
		return true;
	}

Mas é preciso verificar o height com o y também.

V

seria assim?

floa posX = 200;
float posY = 100;

public boolean onTouch(View v, MotionEvent event) {  
		switch(event.getAction()){  
			case MotionEvent.ACTION_DOWN:{  
				if(event.getX() > posX && event.getX() < posX + menuNovoJogo.getWidth() && (event.getY() > posY && event.getY() < posY + menuNovoJogo.getWidth()) ){ 
						posX = 500;
				}  
			break;  
			}  
		}  

		return true;  
	}

se for assim, não aconteceu nada;

Marky.Vasconcelos

Se ele entrar no if o usuario clicou no menu, e voce deve executar a ação que deseja.

Não aconteceu nada por que a unica coisa que voce fez dentro do if foi atribuir 500 a posX

V

E agora?
Será que fiz algo errado?
Estou desesperado.
Desculpa Marky te aperriar =)

public boolean onTouch(View v, MotionEvent event) {  
		switch(event.getAction()){  
			case MotionEvent.ACTION_DOWN:{  
				if(event.getX() > posX && event.getX() < posX + menuNovoJogo.getWidth() && (event.getY() > posY && event.getY() < posY + menuNovoJogo.getWidth()) ){ 
						new RedeDroid().carregaTelaPrincipal();
				}  
			break;  
			}  
		}
public class RedeDroid extends Activity {

	   
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        carregaTelaMenu();
        
     
    }
    

    public void carregaTelaMenu(){
		setContentView(R.layout.menu);
		
    }

    public void carregaTelaPrincipal(){
		setContentView(R.layout.telaJogo);
    }
V

Seria mais interessante fazer esse menu com ImageButton e apenas o jogo em si com canvas?

Estou pensando em colocar imageButton sem desenhar com canvas, pois nao consigo fazer isso.

O que me diz?

Marky.Vasconcelos

Qualquer um dos dois é viavel.

O problema ali é que voce só está chamando um método.

Voce precisa usar um Intent para abrir outra Activity.

V

Marky,

Resolvi criar os imageButtons mesmo.
Mas em relação ao exemplo, como ficaria a questão de usar o intent?

Outra coisa,
Tenho uma tela que deve ter um backgroud, um imageButton e um texto escrito com canvas.
Quando eu coloco em Graphical Layout aparece do jeito que eu quero, porém, quando coloco pra rodar, o imaggeButton e o background desaparece, ficando apenas o drawText();

package com.br.android;




import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;

import android.os.Bundle;
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;

public class TelaInstrucoes extends View {
	Paint paint;
	Resources res = this.getResources();
	
	public TelaInstrucoes(Context context) {
		super(context);
	
		
	}
	public TelaInstrucoes(Context context, AttributeSet attrs) {
		super(context, attrs);
	
	}
	public TelaInstrucoes(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		
		
	}
    public void onDraw(Canvas canvas){
    	paint = new Paint();
    	paint.setColor(Color.WHITE);
    	paint.setTextSize(10);
    	canvas.drawText("Fazendo teste sobre o texto na tela", 10, 90, paint);
    	canvas.drawText("Fazendo teste sobre o texto na tela linha 2", 10, 100, paint);
    }
    
 
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:background="@drawable/back"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent" android:id="@layout/telainstrucoes">


<AbsoluteLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/AbsoluteLayout02">
<ImageView android:layout_width="wrap_content" android:layout_x="160dip" android:layout_y="5dip" android:layout_height="wrap_content" android:src="@drawable/logomenu" android:id="@+id/ImageView01"></ImageView>
<ImageView android:id="@+id/ImageView02" android:layout_width="wrap_content" android:layout_x="10dip" android:layout_y="70dip" android:layout_height="wrap_content" android:src="@drawable/instrucoestela"></ImageView>
<com.br.android.TelaInstrucoes
	 android:layout_width="fill_parent"
	 android:layout_height="fill_parent" >
</com.br.android.TelaInstrucoes>
</AbsoluteLayout>


</LinearLayout>
V

A parte do canvas consegui resolver.

Em relação ao Intent, ainda não consegui.
Pode me ajudar?

Marky.Vasconcelos

Executa isso de dentro da sua atividade que quer chamar a outra.

startActivity(new Intent(this, RedeDroid.class));
V

Marky,
Deu muito certo não.

button = (Button) findViewById(R.id.botaoOk);
	    	
	  	button.setOnClickListener(new View.OnClickListener() {
				
				public void onClick(View v) {
					new RedeDroid().carregarTelaNovoJogo();
				}
			});
	    }
public void carregarTelaNovoJogo(){
	
		startActivity(new Intent(this,TelaNovoJogo.class));  
	}
Marky.Vasconcelos

Qual é Activity que esta sendo executada, na qual voce quer chamar a segunda?

V

Marky,

Fiz de um jeito aqui e deu certo.

Vamos para outros problemas =).

É o seguinte.

No meu jogo terão várias bolinhas e eu irei clicar nessas bolinhas ligando umas as outras.

1 - Essas bolinhas serão imageButtons ou Bitmaps?
2 - Como que eu faço pra que ao clicar em uma bolinha e ir arrastando até a outra, exiba um traço que vá acompanhando o dedo?

Obg.

P

Ai Marky…ele tá dizendo que quer vc como sócio no game dele a ser publicado no Market. Sendo assim, pode ir ajudando mesmo…

V

boone

Se não quiser ajudar, não atrapalhe.

Marky.Vasconcelos

vasco.fred:
Marky,
1 - Essas bolinhas serão imageButtons ou Bitmaps?
2 - Como que eu faço pra que ao clicar em uma bolinha e ir arrastando até a outra, exiba um traço que vá acompanhando o dedo?

1 - Bitmaps
2 - Basta desenhar uma Linha tendo como extremidades o vetor posição das duas bolinhas.

V

Marky, eu fiz isso mas não consegui nem desenhar a linhda.

public class TelaNovoJogo extends View {
	private Paint paint;
	private Bitmap pc1;
	Resources res = this.getResources();
	int y, x;
	float xPc = 10;
	float yPc = 121;

	public TelaNovoJogo(Context context, String nome) {
		super(context);
		init();
	}

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

	public TelaNovoJogo(Context context, AttributeSet attrs, int defStyle) {
	        super(context, attrs, defStyle);
		init();
	}


	private void init(){
		pc1 = BitmapFactory.decodeResource(res, R.drawable.pc1);
        }

	public void onDraw(Canvas canvas){
		canvas.save();
		paint = new Paint();
		canvas.drawBitmap(pc1, xPc,yPc, null);
		canvas.drawLine(10, 20, 10, y, paint1);
		canvas.restore();
	}

	@Override  
       public boolean onTouchEvent(MotionEvent event){  
		switch (event.getAction()) {  
		case MotionEvent.ACTION_DOWN:
			if(event.getX() > yPc && event.getX() < xPc + pc1.getWidth() && (event.getY() > yPc && event.getY() < yPc + pc1.getWidth()) ){
				x = (int) event.getX();  
				y = (int) event.getY();  
				invalidate();  
			}
			break;  

		}  

		return true;  

	}  

}
Criado 7 de abril de 2011
Ultima resposta 1 de mai. de 2011
Respostas 44
Participantes 6