GameJam 2021 em janeiro (online)
A Global Game Jam está de volta! Num ano atípico, e face as complicações do mundo exterior, o servidor do GameDev.PT abre as portas como espaço e jam site da Global Game Jam Online, com a comunidade juntar-se novamente para mais um fim-de-semana a criar jogos lado-a-lado com o resto do mundo, pela primeira vez em formato online!
Este ano, os jam sites portugueses juntam-se também em parceria como Global Game Jam Portugal para ajudar a levar os jam sites ainda mais longe!
Se queres participar numa game jam, não deixes que a pandemia te impeça! Entre 29 e 31 de Janeiro, participa connosco por 48 horas, forma uma equipa e cria o teu jogo! O evento é aberto a toda a comunidade, e convidamos profissionais, estudantes e amadores a juntarem-se, mesmo que nunca tenham participado numa jam antes!
Queres participar? Entra no nosso Discord e lê a sala #ggj-info para mais informações! Depois disso, inscreve-te no jam site aqui através do site da Global Game Jam!
Todos os anuncios em relação à jam serão feitos através do Discord!
+infos(oficial): LINK
Gamer’s Chest, All-in-One Tabletop Game Organizer
Encontrei este projeto no kickstarter para os jogos de tabuleiro.. tão fixe!
+infos(a campanha): LINK
em kotlin: gps terceira versão com mapa
Adicionar uma dependência via menus no build-gradle (module)
(1)
ficheiro: build-gradle(module)
... dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.core:core-ktx:1.3.2' implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'com.google.android.material:material:1.2.1' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'com.google.android.gms:play-services-location:17.1.0' implementation 'com.google.android.gms:play-services-maps:17.0.0' testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' }
ficheiro: AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="pt.isec.estuda.amov_gpsv1"> <!-- pedir estas permissões --> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <!-- pedir estas permissões para aceder aos mapas e ao estado da rede não são em runtime --> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Amov_gpsv1"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <meta-data android:name="com.google.android.geo.API_KEY" android:value="AIzaSyD4M076vcUKcPZNGlyBzFshU-J4jJ98x5g"/> </application> </manifest>
ficheiro: MainActivity.kt
package pt.isec.estuda.amov_gpsv1 import android.Manifest import android.annotation.SuppressLint import android.content.pm.PackageManager import android.graphics.Color import android.location.Location import android.location.LocationListener import android.location.LocationManager import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log import androidx.core.app.ActivityCompat import com.google.android.gms.location.* import com.google.android.gms.maps.CameraUpdateFactory import com.google.android.gms.maps.GoogleMap import com.google.android.gms.maps.OnMapReadyCallback import com.google.android.gms.maps.SupportMapFragment import com.google.android.gms.maps.model.CameraPosition import com.google.android.gms.maps.model.CircleOptions import com.google.android.gms.maps.model.LatLng import com.google.android.gms.maps.model.MarkerOptions const val TAG = "Location" class MainActivity : AppCompatActivity(), OnMapReadyCallback{ var locEnable = false //caso não ajam permissões lateinit var fLoc : FusedLocationProviderClient val ISEC = LatLng(40.1925, -8.4115) val DEIS = LatLng(40.1925, -8.4128) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) fLoc = FusedLocationProviderClient(this) //pedir o objeto google maps e vai ser necessário o OnMapReadyCallback (supportFragmentManager.findFragmentById(R.id.map) as? SupportMapFragment)?.getMapAsync(this) } override fun onResume() { super.onResume() startLocationServices(true) //para poupanças de energia, ativar o mais tarde possivel } override fun onPause() { super.onPause() //para poupanças de energia, desactivar o mais cedo possivel if(locEnable) { locEnable = false } } override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) //se tivermos as permissões //locationM.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 100f, this) if(requestCode == 1289) { startLocationServices(false) } } fun startLocationServices(askPerm : Boolean) { //1ºprovider, 2º intervalo de segundos,3º distancia minima ,4º o listener //se for for telemovel NETWORK_PROVIDER //dar permissões: ACCESS_FINE_LOCATION //e pedir em runtime, add permissions check if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { //pedir as permissões //&& ou || if (askPerm) { ActivityCompat.requestPermissions(this, arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), 1289) //1289 um valor qualquer! } else { finish() } return } val locRequest = LocationRequest().apply { interval = 4000 priority = LocationRequest.PRIORITY_HIGH_ACCURACY //ocultar para ja estes dois: //fastestInterval = 2000 //maxWaitTime = 10000 //numUpdates /? a ver, quantidade de updates } //activar locEnable = true fLoc.requestLocationUpdates(locRequest, locationCallBack, null) } //função locationCallBack var locationCallBack = object : LocationCallback() { override fun onLocationResult(p0: LocationResult?) { Log.i(TAG, "onLocationAvailability: ") //locations é uma lista de localizações p0?.locations?.forEach { Log.i(TAG, "onLocationAvailability: ${it.latitude} ${it.longitude}") } } } @SuppressLint("MissingPermission") override fun onMapReady(map: GoogleMap?) { //implementar o omMapReady, sendo p0 o ojecto google maps map ?: return //if map == null return map.isMyLocationEnabled = true map.uiSettings.isCompassEnabled = true map.uiSettings.isZoomControlsEnabled = true map.uiSettings.isZoomGesturesEnabled = true val cp = CameraPosition.Builder().target(ISEC).zoom(17f).bearing(0f).tilt(0f).build() map.animateCamera(CameraUpdateFactory.newCameraPosition(cp)) map.addCircle( CircleOptions().center(ISEC).radius(150.0).fillColor(Color.argb(128,128,128,128)).strokeColor(Color.rgb(128,0,0)).strokeWidth(4f) ) val mo = MarkerOptions().position(ISEC).title("ISEC-IPC").snippet("Instituo.....") val isec = map.addMarker(mo) isec.showInfoWindow() map.addMarker(MarkerOptions().position(DEIS).title("DEIS-ISEC")) } }
ficheiro: activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <!-- incluimos o mapa como um fragmento --> <fragment android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" android:name="com.google.android.gms.maps.SupportMapFragment"/> </FrameLayout>
em kotlin: gps segunda versão
Adicionar uma dependência via menus no build-gradle (module)
(1)
(2)
(3)
ficheiro: build-gradle(module)
... dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.core:core-ktx:1.3.2' implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'com.google.android.material:material:1.2.1' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'com.google.android.gms:play-services-location:17.1.0' testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' }
ficheiro: AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="pt.isec.estuda.amov_gpsv1"> <!-- pedir estas permissões --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Amov_gpsv1"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
ficheiro: MainActivity.kt
package pt.isec.estuda.amov_gpsv1 import android.Manifest import android.content.pm.PackageManager import android.location.Location import android.location.LocationListener import android.location.LocationManager import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log import androidx.core.app.ActivityCompat import com.google.android.gms.location.* const val TAG = "Location" class MainActivity : AppCompatActivity() { var locEnable = false //caso não ajam permissões lateinit var fLoc : FusedLocationProviderClient override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) fLoc = FusedLocationProviderClient(this) } override fun onResume() { super.onResume() startLocationServices(true) //para poupanças de energia, ativar o mais tarde possivel } override fun onPause() { super.onPause() //para poupanças de energia, desactivar o mais cedo possivel if(locEnable) { locEnable = false } } override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) //se tivermos as permissões //locationM.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 100f, this) if(requestCode == 1289) { startLocationServices(false) } } fun startLocationServices(askPerm : Boolean) { //1ºprovider, 2º intervalo de segundos,3º distancia minima ,4º o listener //se for for telemovel NETWORK_PROVIDER //dar permissões: ACCESS_FINE_LOCATION //e pedir em runtime, add permissions check if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { //pedir as permissões //&& ou || if (askPerm) { ActivityCompat.requestPermissions(this, arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), 1289) //1289 um valor qualquer! } else { finish() } return } val locRequest = LocationRequest().apply { interval = 4000 priority = LocationRequest.PRIORITY_HIGH_ACCURACY //ocultar para ja estes dois: //fastestInterval = 2000 //maxWaitTime = 10000 //numUpdates /? a ver, quantidade de updates } //activar locEnable = true fLoc.requestLocationUpdates(locRequest, locationCallBack, null) } } //função locationCallBack var locationCallBack = object : LocationCallback() { override fun onLocationResult(p0: LocationResult?) { Log.i(TAG, "onLocationAvailability: ") //locations é uma lista de localizações p0?.locations?.forEach { Log.i(TAG, "onLocationAvailability: ${it.latitude} ${it.longitude}") } } }
Com esta versão são feitos updates mais rapidamente, com a ajuda do LocationRequest.PRIORITY_HIGH_ACCURACY
este é o método recomendado pela google..
em kotlin: gps primeira versão
ficheiro: AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="pt.isec.estuda.amov_gpsv1"> <!-- pedir estas permissões --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Amov_gpsv1"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
ficheiro: MainActivity.kt
package pt.isec.estuda.amov_gpsv1 import android.Manifest import android.content.pm.PackageManager import android.location.Location import android.location.LocationListener import android.location.LocationManager import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log import androidx.core.app.ActivityCompat const val TAG = "Location" class MainActivity : AppCompatActivity(), LocationListener { lateinit var locationM : LocationManager var locEnable = false //caso não ajam permissões override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) locationM = getSystemService(LOCATION_SERVICE) as LocationManager } override fun onResume() { super.onResume() startLocationServices(true) //para poupanças de energia, ativar o mais tarde possivel } override fun onPause() { super.onPause() //para poupanças de energia, desactivar o mais cedo possivel if(locEnable) { locationM.removeUpdates(this) locEnable = false } } override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) //se tivermos as permissões //locationM.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 100f, this) if(requestCode == 1289) { startLocationServices(false) } } fun startLocationServices(askPerm : Boolean){ //1ºprovider, 2º intervalo de segundos,3º distancia minima ,4º o listener //se for for telemovel NETWORK_PROVIDER //dar permissões: ACCESS_FINE_LOCATION //e pedir em runtime, add permissions check if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { //pedir as permissões //&& ou || if(askPerm) { ActivityCompat.requestPermissions(this, arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), 1289) //1289 um valor qualquer! }else{ finish() } return } locationM.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 100f, this) locEnable = true //outras: //addProximityAlert, funções de proximidade para um determinado local //addNmeaListener, ir buscar as mensagens de baixo nivel que um chip gps consegue obter //requestSingleUpdate, ir buscar apenas um update(uma localização armazenada) //getLastKnownLocation, obter um objeto Location, obtemos logo uma localização mesmo que não seja correta //providers, acerca dos requisitos da rede } override fun onLocationChanged(location: Location) { val latitude = location.latitude val longitude = location.longitude Log.i(TAG, "onLocationChanged: $latitude $longitude") //a ver o location.distanceTo() } }
Magallanes_ICC :
Está a decorrer um “Open Call Programa de Apoio ao Empreendedorismo Criativo” onde se inclui a apresentação para Jogos/ softwares educativos
+infos(oficial): https://arterialab.uevora.pt/criativos/
Proposta de trabalho (em Gaia)
“SABER PORTO is NOW hiring the best:
– CHARACTER ARTISTS
– ENVIRONMENT ARTISTS
– TEXTURE ARTISTS
If you’re interested to work in Porto and develop AAA games, send your CV and PORTFOLIO to jobs@saber3d.pt.”
+infos(rede social): LINK
+infos(oficial): http://www.bigmoonstudios.com/
Humble Software Bundle: Maps Extravaganza Encore (uma campanha)
Esta é outra campanha da Humble mas o caso não é tanto para GameDev mas para jogos de tabuleiro. Tratam-se de várias ferramentas, softwares que permite criar mapas para jogos de tabuleiro. Interessante este tipo de programas, que eu não conhecia :) (também não tinha procurado). Da lista de prendas desta campanha consta:
Token Treasury: Monsters
Battle Maps Collection
Floorplan Collection
Sources Maps: Castles
Symbol Set 2: Fantasy Floorplans
Source Maps: Temples, Tombs and Catacombs
Tome of Ultimate Mapping
Perspectives 3
Campaign Cartographer 3+ One Year License
Campaign Cartographer 3+ Lifetime License
City Designer 3
Dungeon Designer 3
+infos(a campanha): LINK
Humble Game Dev Map & Level Creator Bundle, Humble software bundle (uma campanha)
Está a decorrer outra campanha no Humble com algumas coisas interessantes para acerca de GameDev, nomeadamente alguns programas para a construção de mapas e níveis de jogos. Da lista consta:
Egyptian Tileset
World Map Pixel Art Tileset
Super Pixel Dungeon
Fantasy Map
Night City Game Level Kit
Tropical Island 2d game Tileset
Desert Tileset
Fantasy Village
Game Level Map Set Kit
Fantasy Jungle Pixel Art Tileset
House Interiors Tileset Pack
City Street Tileset Pack
WiraWiri Game Level Map Builder
Misty Forest Ground Tiles
595 Medieval 2D Game Asset Pack
Platformer Game Tile Set 3
Simple RPG Tileset
Platformer Game Tile Set 1
Super Pixel Ice Cavern Tileset
Cartoon Platformer TilesetPack
Mega Factory Scene Creation Pack
Pixel Art Tileset Collection
Game Level Map – 9 Different Worlds
Underwater Tile Set
Isometric Forest
Wolfsong Tilesets
Top Down Tileset Interior
16 Jump Vertical Game Backgrounds
2D Isometric Starter Style Kit
The Dungeon Top Down Tileset
Game Level Map Pack Side Scrolling
Top Down Tileset Forest
Mega Castle & Dungeon Pack
Game Level Map Creator For Water Levels
Landscape Constructor Set
Woodlands Level Map Creator
Green Greens Forest Platformer Tileset
+infos(a campanha): LINK
Proposta de trabalho (em Gaia)
“SABER PORTO is hiring the best:
– CONCEPT ARTISTS
– GAME DESIGNERS
– VISUAL FX ARTISTS
If you’re interested to work in Porto and develop AAA games, send your CV and PORTFOLIO to jobs@saber3d.pt”
+infos(rede social): LINK
+infos(oficial): http://www.bigmoonstudios.com/
Proposta de trabalho (em Gaia)
SABER PORTO continues to grow its fantastic team in PORTUGAL! WE ARE HIRING:
– IT MANAGER
– HUMAN RESOURCES MANAGER
– ADMINISTRATIVE ASSISTANT
– ASSISTANT PRODUCER
– CINEMATICS & VIDEO EDITOR
– COMMUNITY MANAGER
If you’re interested, send your CV to jobs@saber3d.pt
+infos(rede social): LINK
+infos(oficial): http://www.bigmoonstudios.com/
em kotlin: uma recyclerView
ficheiro: MainActivity.kt
package pt.deis.estuda.estudoslistview2 import android.content.Intent import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.view.View class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } fun onRecyclerView(view: View) { val intent = Intent(this,RecyclerViewActivity::class.java) startActivity(intent) } }
ficheiro: activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:onClick="onRecyclerView" android:id="@+id/button" android:layout_width="0dp" android:layout_height="wrap_content" android:padding="16dp" android:text="recycler view" android:textSize="24sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
ficheiro: activity_recycler_view.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" xmlns:app="http://schemas.android.com/apk/res-auto" app:cardCornerRadius="6dp" app:cardElevation="6dp" android:layout_margin="6dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:textStyle="bold" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:id="@+id/recyclerTV1" android:textSize="24sp" android:text="Text 1" /> <TextView android:background="#f0f0f0" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:id="@+id/recyclerTV2" android:textSize="20sp" android:text="Text 2" /> <TextView android:background="#808080" android:textColor="#ffffff" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="right" android:id="@+id/recyclerTV3" android:textSize="16sp" android:text="Text 3" /> </LinearLayout> </androidx.cardview.widget.CardView>
ficheiro: activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".RecyclerViewActivity" android:padding="16dp"> <androidx.recyclerview.widget.RecyclerView android:padding="4dp" android:id="@+id/recyclerviewList" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
ficheiro: AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="pt.deis.estdua.arecyclerview"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.ARecyclerView"> <activity android:name=".RecyclerViewActivity" android:label="ListView" android:parentActivityName=".MainActivity" /> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
ficheiro: RecyclerViewActivity.kt
package pt.deis.estuda.arecyclerview import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.StaggeredGridLayoutManager import kotlinx.android.synthetic.main.activity_recycler_view.* import kotlin.random.Random class RecyclerViewActivity : AppCompatActivity() { data class Dados(val str1:String,val str2 : String, val str3:String) val data = arrayListOf<Dados>() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_recycler_view) supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.subtitle = "Exemplo Recycler View" //sorterar numeros aleatoriamente repeat(Random.nextInt(10,20)) { val item = Dados("Titulo ${Random.nextInt(0,1000)}",getStr(50,400),getStr(5,20)) data.add(item) } //atribuir um layoutManager, um gestor para organizar os objectos, existem assim 3 tipos //LinearLayoutManager ou GridLayoutManager ou StaggeredGridLayoutManager //LinearLayoutManager.VERTICA - > lista com scroll na vertical //recyclerviewList.layoutManager = LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false) //recyclerviewList.layoutManager = GridLayoutManager(this,2,GridLayoutManager.VERTICAL,false) recyclerviewList.layoutManager = StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL) //MyRVAdapter derivado do RecyclerView.Adapter recyclerviewList.adapter = MyRVAdapter(data) } fun getStr(minc:Int,maxc: Int) : String { var str = "" val nrc = Random.nextInt(minc,maxc) repeat(nrc) { str += Random.nextInt(65,90).toChar() } return str } //é obrigatório o objecto ViewHolder, que representa cada um dos itens que vai ser visualizado class MyRVAdapter(val data : ArrayList<Dados>) : RecyclerView.Adapter<MyRVAdapter.MyViewHolder>() { class MyViewHolder(view : View) : RecyclerView.ViewHolder(view) { var tv1 : TextView = view.findViewById(R.id.recyclerTV1) var tv2 : TextView = view.findViewById(R.id.recyclerTV2) var tv3 : TextView = view.findViewById(R.id.recyclerTV3) //não é necessário.. e o update vai ser chamado pelo onBindViewHolder fun update(str1:String,str2:String,str3:String) { tv1.text = str1 tv2.text = str2 tv3.text = str3 } } //criar as vistas override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.recyclerview_item ,parent,false) //e é retornado no contexto do MyViewHolder return MyViewHolder(view) } //inflate de um layout override fun onBindViewHolder(holder: MyViewHolder, position: Int) { holder.update(data[position].str1,data[position].str2,data[position].str3) } //método para saber quantos elementos tem a lista override fun getItemCount(): Int = data.size } }
ficheiro: build.gralde (Module)
plugins { id 'com.android.application' id 'kotlin-android' id 'kotlin-android-extensions' // obrigatorio para aceder aos diferentes layouts sem usar o findId } ...
em kotlin: uma ListView XML array adapter personalizada v4 (destaque)
ficheiro: MainActivity.kt
package pt.deis.estuda.estudoslistview2 import android.content.Intent import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.view.View const val TAG = "ListView" class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } fun onList4View(view: View) { val intent = Intent(this,ListView4Activity::class.java) startActivity(intent) } }
ficheiro: activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:onClick="onList4View" android:id="@+id/button" android:layout_width="0dp" android:layout_height="wrap_content" android:padding="16dp" android:text="ListView XML array adapter personalizado v4" android:textSize="24sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
ficheiro: activity_list4_view.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ListView4Activity"> <ListView android:id="@+id/quartaListView" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout>
ficheiro: arrays.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="dados_str"> <item>Portugal</item> <item>Espanha</item> <item>Franca</item> <item>Italia</item> <item>Alemanha</item> <item>Belgica</item> <item>Holanda</item> <item>Austria</item> <item>Luxemburgo</item> <item>Suecia</item> <item>Dinamarca</item> <item>Irlanda</item> <item>Croacia</item> <item>Eslovenia</item> <item>Eslovaquia</item> <item>Estonia</item> <item>Polonia</item> <item>Grecia</item> <item>Finlandia</item> <item>Chipre</item> <item>Malta</item> <item>Bulgaria</item> <item>Hungria</item> <item>Romenia</item> <item>Rep. Checa</item> <item>Letonia</item> <item>Lituania</item> </string-array> </resources>
ficheiro: AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="pt.deis.estuda.estudoslistview4"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Estudoslistview4"> <activity android:name=".ListView4Activity" android:label="ListView" android:parentActivityName=".MainActivity" /> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
ficheiro: ListView4Activity.kt
package pt.deis.estuda.estudolistview4 import android.graphics.Color import android.os.Bundle import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.BaseAdapter import android.widget.ImageView import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import kotlinx.android.synthetic.main.activity_list4_view.* import kotlin.random.Random class ListView4Activity : AppCompatActivity() { data class Pais (val nome : String, var habitantes:Int) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_list4_view) supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.subtitle = "Exemplo 4" val paises = resources.getStringArray(R.array.dados_str) paises.sort() val data = arrayListOf<Pais>() for(p in paises) { val item = Pais(p, Random.nextInt(100000,99000000)) data.add(item) } val adapter = MyAdapter(data) quartaListView.adapter = adapter quartaListView.setOnItemClickListener() { parent, view, pos, id -> Log.i(TAG, "Item: $pos $id") } } //adapter personalizado derivado do BaseAdapter class MyAdapter(val data : ArrayList<Pais>) : BaseAdapter() { val imgs = arrayOf( android.R.drawable.ic_menu_agenda, android.R.drawable.ic_menu_camera, android.R.drawable.ic_menu_call, android.R.drawable.ic_menu_compass ) //sendo MyAdapater abstracta tenho que implementar os 4 próximos métodos //método devolve quantos items (usar do construtor do data) override fun getCount(): Int = data.size //método retorna o elemento de dados que está numa posição override fun getItem(position: Int): Any { return data[position] } //método para uma posição indica override fun getItemId(position: Int): Long = position.toLong() //metodo para retornar uma view, é um layout com tudo preenchido com o que queremos //o elemento neste caso é o position override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View { //fazer o inflate do listview_item val view = LayoutInflater.from(parent!!.context).inflate(R.layout.listview4_item, parent, false) //para preencher os campos view.findViewById<TextView>(R.id.tv1).text = data[position].nome //usar o tv1 e tv2 para inserir os dados view.findViewById<TextView>(R.id.tv2).apply { text = data[position].habitantes.toString() //filtro dos dados dependendo das cores if (data[position].habitantes > 80000000) { setBackgroundColor(Color.rgb(128, 0, 0)) setTextColor(Color.WHITE) } //para reduzir o numero de abitantes quanto se dá um toque setOnClickListener { data[position].habitantes = (data[position].habitantes * 0.5).toInt() this@MyAdapter.notifyDataSetChanged() } //quando se faz o long click reponho o numero de habitantes setOnLongClickListener { data[position].habitantes = 99_000_000 this@MyAdapter.notifyDataSetChanged() true } } //associo uma imagem, sorteadas view.findViewById<ImageView>(R.id.ivImg) .setImageResource(imgs[Random.nextInt(imgs.size)]) return view } } }
ficheiro: listview4_item.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="match_parent" android:padding="4dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="4dp" android:background="#800000"> <ImageView android:id="@+id/ivImg" android:src="@android:drawable/ic_dialog_map" android:layout_width="32dp" android:layout_height="32dp" /> <TextView android:textStyle="bold" android:padding="4dp" android:textSize="20sp" android:text="text1" android:layout_width="0dp" android:layout_weight="2" android:layout_height="wrap_content" android:id="@+id/tv1" android:textColor="#000000" android:background="#f0d080"/> <TextView android:padding="4dp" android:textSize="20sp" android:gravity="right" android:text="text2" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:id="@+id/tv2" android:background="#80d0f0"/> </LinearLayout> </FrameLayout>
ficheiro: build.gralde (Module)
plugins { id 'com.android.application' id 'kotlin-android' id 'kotlin-android-extensions' // obrigatorio para aceder aos diferentes layouts sem usar o findId } ...
em kotlin: uma ListView XML array adapter personalizada v2 (numeros)
ficheiro: MainActivity.kt
package pt.deis.estuda.estudoslistview2 import android.content.Intent import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.view.View const val TAG = "ListView" class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } fun onList2View(view: View) { val intent = Intent(this,ListView3Activity::class.java) startActivity(intent) } }
ficheiro: activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:onClick="onList2View" android:id="@+id/button" android:layout_width="0dp" android:layout_height="wrap_content" android:padding="16dp" android:text="ListView XML array adapter personalizado v2" android:textSize="24sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
ficheiro: activity_list3_view.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ListView3Activity"> <ListView android:id="@+id/terceiraListView" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout>
ficheiro: arrays.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="dados_str"> <item>Portugal</item> <item>Espanha</item> <item>Franca</item> <item>Italia</item> <item>Alemanha</item> <item>Belgica</item> <item>Holanda</item> <item>Austria</item> <item>Luxemburgo</item> <item>Suecia</item> <item>Dinamarca</item> <item>Irlanda</item> <item>Croacia</item> <item>Eslovenia</item> <item>Eslovaquia</item> <item>Estonia</item> <item>Polonia</item> <item>Grecia</item> <item>Finlandia</item> <item>Chipre</item> <item>Malta</item> <item>Bulgaria</item> <item>Hungria</item> <item>Romenia</item> <item>Rep. Checa</item> <item>Letonia</item> <item>Lituania</item> </string-array> </resources>
ficheiro: AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="pt.deis.estuda.estudoslistview3"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Estudoslistview3"> <activity android:name=".ListView3Activity" android:label="ListView" android:parentActivityName=".MainActivity" /> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
ficheiro: ListView3Activity.kt
package pt.deis.estuda.estudolistview3 import android.os.Bundle import android.util.Log import android.widget.SimpleAdapter import androidx.appcompat.app.AppCompatActivity import kotlinx.android.synthetic.main.activity_list3_view.* import kotlin.random.Random class ListView3Activity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_list3_view) supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.subtitle = "Exemplo 3" val paises = resources.getStringArray(R.array.dados_str) paises.sort() /* val data1 = mapOf("valor1" to 10, "valor2" to 20) val data2 = mapOf("valor1" to 11, "valor2" to 21) val data = mutableListOf(data1,data2) */ val data = mutableListOf<Map<String,Any>>() //Any() para ser qualquer tipo de dados //val i = Random.nextInt(10,20) for(p in paises) { val item = mapOf<String,Any>("valor1" to p, "valor2" to Random.nextInt(100000,99000000), "imagem" to android.R.drawable.ic_menu_compass) data.add(item) } val adapter = SimpleAdapter(this, data, R.layout.listview3_item, arrayOf("valor1","valor2","imagem"), intArrayOf(R.id.tv1, R.id.tv2, R.id.ivImg) ) //tv1 (recebe valor1), tv2 (recebe valor2)... dados das linhas terceiraListView.adapter = adapter terceiraListView.setOnItemClickListener() { parent, view, pos, id -> Log.i(TAG, "Item: $pos $id") } } }
ficheiro: listview3_item.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="match_parent" android:padding="4dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="4dp" android:background="#800000"> <ImageView android:id="@+id/ivImg" android:src="@android:drawable/ic_dialog_map" android:layout_width="32dp" android:layout_height="32dp" /> <TextView android:textStyle="bold" android:padding="4dp" android:textSize="20sp" android:text="text1" android:layout_width="0dp" android:layout_weight="2" android:layout_height="wrap_content" android:id="@+id/tv1" android:textColor="#000000" android:background="#f0d080"/> <TextView android:padding="4dp" android:textSize="20sp" android:gravity="right" android:text="text2" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:id="@+id/tv2" android:background="#80d0f0"/> </LinearLayout> </FrameLayout>
ficheiro: build.gralde (Module)
plugins { id 'com.android.application' id 'kotlin-android' id 'kotlin-android-extensions' // obrigatorio para aceder aos diferentes layouts sem usar o findId } ...
em kotlin: uma ListView XML array adapter personalizada
ficheiro: MainActivity.kt
package pt.deis.estuda.estudoslistview2 import android.content.Intent import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.view.View const val TAG = "ListView" class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } fun onList2View(view: View) { val intent = Intent(this,ListView2Activity::class.java) startActivity(intent) } }
ficheiro: activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:onClick="onList2View" android:id="@+id/button" android:layout_width="0dp" android:layout_height="wrap_content" android:padding="16dp" android:text="ListView XML array adapter personalizado" android:textSize="24sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
ficheiro: activity_list2_view.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ListView2Activity"> <ListView android:id="@+id/segundaListView" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout>
ficheiro: arrays.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="dados_str"> <item>Portugal</item> <item>Espanha</item> <item>Franca</item> <item>Italia</item> <item>Alemanha</item> <item>Belgica</item> <item>Holanda</item> <item>Austria</item> <item>Luxemburgo</item> <item>Suecia</item> <item>Dinamarca</item> <item>Irlanda</item> <item>Croacia</item> <item>Eslovenia</item> <item>Eslovaquia</item> <item>Estonia</item> <item>Polonia</item> <item>Grecia</item> <item>Finlandia</item> <item>Chipre</item> <item>Malta</item> <item>Bulgaria</item> <item>Hungria</item> <item>Romenia</item> <item>Rep. Checa</item> <item>Letonia</item> <item>Lituania</item> </string-array> </resources>
ficheiro: AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="pt.deis.estuda.estudoslistview2"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Estudoslistview2"> <activity android:name=".ListView2Activity" android:label="ListView" android:parentActivityName=".MainActivity" /> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
ficheiro: ListView2Activity.kt
package pt.deis.estuda.estudolistview import android.os.Bundle import android.util.Log import android.widget.ArrayAdapter import androidx.appcompat.app.AppCompatActivity import kotlinx.android.synthetic.main.activity_list2_view.* class ListView2Activity : AppCompatActivity() { var flag = false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_list2_view) supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.subtitle = "Exemplo 2" val paises = resources.getStringArray(R.array.dados_str) paises.sort() //id do elemento das strings ->,R.id.tv1 val adapter1 = ArrayAdapter<String>(this,R.layout.listview2_item,R.id.tv1,paises) //a segunda caixa de texto -> R.id.tv2 val adapter2 = ArrayAdapter<String>(this,R.layout.listview2_item,R.id.tv2,paises) segundaListView.adapter = adapter1 segundaListView.setOnItemClickListener() { parent, view, pos, id -> Log.i(TAG, "Item: $pos $id") //adapter1.notifyDataSetChanged() //serve para forçar o actualizar os dados segundaListView.adapter = if (flag) adapter1 else adapter2 flag = !flag } } }
ficheiro: listview2_item.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="match_parent" android:padding="4dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="4dp" android:background="#800000"> <ImageView android:id="@+id/ivImg" android:src="@android:drawable/ic_dialog_map" android:layout_width="32dp" android:layout_height="32dp" /> <TextView android:textStyle="bold" android:padding="4dp" android:textSize="20sp" android:text="text1" android:layout_width="0dp" android:layout_weight="2" android:layout_height="wrap_content" android:id="@+id/tv1" android:textColor="#000000" android:background="#f0d080"/> <TextView android:padding="4dp" android:textSize="20sp" android:gravity="right" android:text="text2" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:id="@+id/tv2" android:background="#80d0f0"/> </LinearLayout> </FrameLayout>
ficheiro: build.gralde (Module)
plugins { id 'com.android.application' id 'kotlin-android' id 'kotlin-android-extensions' // obrigatorio para aceder aos diferentes layouts sem usar o findId } ...
em kotlin: uma ListView XML array adapter
ficheiro: MainActivity.kt
package pt.deis.estuda.estudolistview import android.content.Intent import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.view.View const val TAG = "ListView" class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } //nvoas actividades para fun onListView1(view: View) { val intent = Intent(this,ListView1Activity::class.java) startActivity(intent) } }
ficheiro: activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#f0f0f0" android:padding="16dp" tools:context=".MainActivity"> <Button android:onClick="onListView1" android:id="@+id/button" android:layout_width="0dp" android:layout_height="wrap_content" android:padding="16dp" android:text="ListView XML array adapter" android:textSize="24sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
ficheiro: activity_list_view.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ListView1Activity"> <ListView android:id="@+id/primeiraListView" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout>
ficheiro: arrays.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="dados_str"> <item>Portugal</item> <item>Espanha</item> <item>Franca</item> <item>Italia</item> <item>Alemanha</item> <item>Belgica</item> <item>Holanda</item> <item>Austria</item> <item>Luxemburgo</item> <item>Suecia</item> <item>Dinamarca</item> <item>Irlanda</item> <item>Croacia</item> <item>Eslovenia</item> <item>Eslovaquia</item> <item>Estonia</item> <item>Polonia</item> <item>Grecia</item> <item>Finlandia</item> <item>Chipre</item> <item>Malta</item> <item>Bulgaria</item> <item>Hungria</item> <item>Romenia</item> <item>Rep. Checa</item> <item>Letonia</item> <item>Lituania</item> </string-array> </resources>
ficheiro: AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="pt.deis.estuda.estudolistview"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Estudolistview"> <activity android:name=".ListView1Activity" android:label="ListView" android:parentActivityName=".MainActivity" /> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
ficheiro: ListView1Activity.kt
package pt.deis.estuda.estudolistview import android.os.Bundle import android.util.Log import android.widget.ArrayAdapter import androidx.appcompat.app.AppCompatActivity import kotlinx.android.synthetic.main.activity_list_view.* class ListView1Activity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_list_view) supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.subtitle = "Exemplo XML array list" //uma lista não ordenada em arrays.xml val paises = resources.getStringArray(R.array.dados_str) paises.sort() //usar um adapter para mostrar a listview //contexto (actividades), layout que só tem uma textview, a fonte dos dados (array das strings) val adapter = ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,paises) primeiraListView.adapter = adapter primeiraListView.setOnItemClickListener() { parent, view, pos, id -> Log.i(TAG, "Item: $pos $id") } } }
ficheiro: build.gralde (Module)
plugins { id 'com.android.application' id 'kotlin-android' id 'kotlin-android-extensions' // obrigatorio para aceder aos diferentes layouts sem usar o findId } ...
GameDevCamp em Portugal, 7ª edição.
+infos(oficial): https://2020.gamedevcamp.org/
Proposta de trabalho
Na Fun Punch Games estamos à procura de um narrative designer/writer para um dos nossos projectos, em regime freelance. Alguém que perceba as possibilidade e limitações da escrita para videojogos, a sua proximidade com as mecânicas de jogo e os seus sistemas, os personagens, sítios, temas e situações associadas. Que saiba como “traduzir” mecânicas para histórias e vice-versa. Alguém que goste de trabalhar em equipa, de discutir ideias e implementação, que queira crescer!
Requisitos:
– Portfolio
– Experiência prévia
– Excelente nível de inglês: muito importante!
Enviem as vossas candidaturas para jobs@funpunchgames.com com o assunto “Narrative Designer”
+infos(oficial): https://funpunchgames.com/
em kotlin: uma calculadora
ficheiro: MainActivity.kt
package pt.deis.estuda.calculadora import android.graphics.Color import android.icu.number.NumberFormatter import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.view.View import android.widget.Button import android.widget.TextView class MainActivity : AppCompatActivity() { lateinit var tvDisplay: TextView //variave para ligar a maquina var strDisplay = "0.0" var novoNumero = true //para tratar do % val numeroCorente : Double //caso dê erro converter fica com 0.0 //o então escrever error get()=strDisplay.toDoubleOrNull() ?: 0.0 //variavel para lidar com a operação //v1 /* enum class Ops{ NONE, ADD, SUB, MUL, DIv } var op = Ops.NONE */ //v2 //id da operação var operador = 0 //alterar a cor do operador set(value){ if(field !=0 ){ findViewById<Button>(field).setTextColor(Color.BLACK) } if(value !=0){ findViewById<Button>(value).setTextColor(Color.GREEN) } field =value } var numeroAntigo = 0.0 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) tvDisplay = findViewById(R.id.tvDisplay) updateDisplay() //para mostrar o 0.0 } fun updateDisplay(){ tvDisplay.text = strDisplay } fun onDigit(view: View) { ///ir buscar o texto do botão e adicionar à caixa val btn = view as Button //para resolver a situaçãod e ser a primeira vez if(novoNumero) { strDisplay = btn.text.toString() } else { strDisplay += btn.text //concatenar ao que lá está } updateDisplay() //para que efectivamente faça a concatenação novoNumero = false } fun onPonto(view: View) { //só pode exisir um ponto no numero if(novoNumero) { strDisplay = "0." }else{ //adicionar o ponto, mas testar se já existe if(strDisplay.contains('.')) return strDisplay += "." } updateDisplay() novoNumero = false } fun onAC(view: View) { strDisplay = "0.0" novoNumero = true updateDisplay() } fun onPM(view: View) { //o sinal do mais menos if(strDisplay[0] == '-'){ strDisplay = strDisplay.substring(1) }else{ //ou strDisplay = "-"+strDisplay //v1 strDisplay = "-$strDisplay" //v2 } updateDisplay() } fun onPer(view: View) { //dividir o valor que existe por 100 strDisplay = "" + numeroCorente / 100.0 updateDisplay() //talvez não usar o true //true: não permite acrescentar mais caracteres novoNumero = true } //versão individual do onOper //v1 fun onMais(view: View) {} fun onSub(view: View) {} fun onDiv(view: View) {} fun onMultiplica(view: View) {} //v2 fun onOper(view : View){ //manter as operações if(operador != 0 && !novoNumero){ onIgual(view) } numeroAntigo = numeroCorente novoNumero = true operador = view.id } fun onIgual(view: View) { var calculo = 0.0 when(operador){ R.id.bntMais -> calculo = numeroCorente + numeroAntigo R.id.btnMul -> calculo = numeroCorente * numeroAntigo R.id.bntSub -> calculo = numeroAntigo - numeroCorente R.id.bntDiv -> calculo = if(numeroCorente != 0.0) numeroAntigo / numeroCorente else 0.0 //caso não tenha operador para fazer else -> return } //actualizar de seguida o display strDisplay = "$calculo" novoNumero = true operador = 0 //manter o numero numeroAntigo = calculo updateDisplay() } }
ficheiro: themes.xml
<resources xmlns:tools="http://schemas.android.com/tools"> <!-- Base application theme. --> <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cstyle%20name%3D%22Theme.Calculadora%22%20parent%3D%22Theme.AppCompat.Light.DarkActionBar%22%3E%0A%20%20%20%20%20%20%20%20%3C!--%20alterar%20o%20tema%20aqui.%20--%3E%0A%0A%20%20%20%20%20%20%20%20%3C!--%20cor%20preta%20default%20--%3E%0A%20%20%20%20%20%20%20%20%3Citem%20name%3D%22android%3AtextColor%22%3E%23000000%3C%2Fitem%3E%0A%0A%20%20%20%20%3C%2Fstyle%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<style>" title="<style>" /> </resources>
ficheiro: activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" android:orientation="vertical" android:background="#c0c0c0" android:padding="16dp" > <TextView android:id="@+id/tvDisplay" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="0.0" android:gravity="right" android:textSize="24sp" android:padding="16dp" android:background="#ffffc0" android:layout_marginBottom="20dp" /> <!-- android:layout_height="0dp" //distribuir o espaço da mesma forma (é o peso) android:layout_weight="1" //por termos peso a altura tem que ter 0dp --> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="horizontal"> <!-- android:id="@+id/bntAC" //atribuir sempre um id android:layout_weight="1" //distribuir o espaço da mesma forma (é o peso) android:layout_width="0dp" //por termos peso a largura tem que ter 0dp --> <Button android:id="@+id/bntAC" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:text="AC" android:textSize="20sp" android:onClick="onAC" /> <Button android:id="@+id/bntPM" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:text="+/-" android:textSize="20sp" android:onClick="onPM" /> <Button android:id="@+id/bntPerc" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:text="%" android:textSize="20sp" android:onClick="onPer" /> <Button android:id="@+id/bntDiv" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:text="/" android:textSize="20sp" android:onClick="onOper" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="horizontal"> <!-- android:id="@+id/bntAC" //atribuir sempre um id android:layout_weight="1" //distribuir o espaço da mesma forma (é o peso) android:layout_width="0dp" //por termos peso a largura tem que ter 0dp android:onClick="onDigit" é uma funça --> <Button android:id="@+id/bnt7" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:onClick="onDigit" android:text="7" android:textSize="20sp" /> <Button android:id="@+id/bnt8" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:onClick="onDigit" android:text="8" android:textSize="20sp" /> <Button android:id="@+id/bnt9" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:onClick="onDigit" android:text="9" android:textSize="20sp" /> <Button android:id="@+id/btnMul" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:text="*" android:textSize="20sp" android:onClick="onOper" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="horizontal"> <!-- android:id="@+id/bntAC" //atribuir sempre um id android:layout_weight="1" //distribuir o espaço da mesma forma (é o peso) android:layout_width="0dp" //por termos peso a largura tem que ter 0dp --> <Button android:id="@+id/bnt4" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:onClick="onDigit" android:text="4" android:textSize="20sp" /> <Button android:id="@+id/bnt5" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:onClick="onDigit" android:text="5" android:textSize="20sp" /> <Button android:id="@+id/bnt6" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:onClick="onDigit" android:text="6" android:textSize="20sp" /> <Button android:id="@+id/bntSub" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:text="-" android:textSize="20sp" android:onClick="onOper" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="horizontal"> <!-- android:id="@+id/bntAC" //atribuir sempre um id android:layout_weight="1" //distribuir o espaço da mesma forma (é o peso) android:layout_width="0dp" //por termos peso a largura tem que ter 0dp --> <Button android:id="@+id/bnt1" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:onClick="onDigit" android:text="1" android:textSize="20sp" /> <Button android:id="@+id/bnt2" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:onClick="onDigit" android:text="2" android:textSize="20sp" /> <Button android:id="@+id/bnt3" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:onClick="onDigit" android:text="3" android:textSize="20sp" /> <Button android:id="@+id/bntMais" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:text="+" android:textSize="20sp" android:onClick="onOper" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="horizontal"> <!-- android:id="@+id/bntAC" //atribuir sempre um id android:layout_weight="1" //distribuir o espaço da mesma forma (é o peso) android:layout_width="0dp" //por termos peso a largura tem que ter 0dp --> <Button android:id="@+id/bnt0" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="2" android:onClick="onDigit" android:text="0" android:textSize="20sp" /> <Button android:id="@+id/bntPonto" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:text="." android:textSize="20sp" android:onClick="onPonto" /> <Button android:id="@+id/bntIgual" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:text="=" android:textSize="20sp" android:onClick="onIgual" /> </LinearLayout> </LinearLayout>
Laboratório de Jogos do IST: Alumni Meeting 2020
Cheguei a tempo de assistir à palestras do LabJogos, e fiquei a saber de mais um tuga que anda lá por fora a desenvolver o seu percurso no mundo dos videojogos, de nome João Oliveira que trabalha na Ubisoft.
+infos(a conversa): https://fb.watch/1Vk72BUeZN/
Dice Command
Esteve a decorrer uma campanha acerca deste jogo de tabuleiro. Uma vez mais achei interessante o tema… mas achei caro com os portes de envio! Mas fica o registo da sua existência :)
+infos(oficial): https://www.ejectedplanet.com/
+infos(campanha): LINK
Sea of Roses, um videojogo
Sea of Roses
Desenvolvido por: Ariana Parrilha (FBAUL), Andreia Santos Batista (FBAUL) & André Fidalgo Silva (IST)
Humble Game Dev STEM, Humble software bundle (uma campanha)
Está a decorrer mais uma campanha no Humble com algumas coisas interessantes para acerca de GameDev, nomeadamente alguns programas para a construção da documentação e alguns extras para uso com o software Game Creator. Da lista consta:
SoftWeir Game Design Documentation Builder
SoftWeir Project Management Documentation
SoftWeir World Design Worksheet
SoftWeir Map & Dungeon Design Worksheet
SoftWeir User-Interface Design Worksheet
SoftWeir Character & Animation Design Worksheet
SoftWeir Story & Storyboard Design Worksheet
SoftWeir Script & Logic Design Worksheet
SoftWeir Item Design Worksheet
SoftWeir Weapon & Armour Design Worksheet
001 Game Creator
001 Basics E-Book + E-Learning Home Assignments
001 Resource E-Book + E-Learning Home Assignments
DLC 001 Game Creator – Point & Click Adventure Kit
DLC 001 Game Creator – Dragons Den Resource Pack
DLC 001 Game Creator – Retro Fantasy Music Pack Volume 1
DLC 001 Game Creator – Sound Effects Pack Volume 1
DLC 001 Game Creator – Enhanced RPG Kit
DLC 001 Game Creator – 3D FPS / Survival Horror Kit
DLC 001 Game Creator – MMORPG Kit
DLC 001 Game Creator – Visual Novel Kit
+infos(campanha): LINK
VGPT, Arquivo online de videojogos portugueses
Um site interessante, que ainda está a crescer, mas que funciona como uma espécie de museu/catálogo virtual acerca dos videojogos que foram desenvolvidos em Portugal ao longos dos tempos.. a acompanhar.
+infos(oficial): https://videogamept.wordpress.com/