Tag: amov
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()
}
}
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
}
...
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>
amov o inicio
//num projeto
>gradle scripts
build.gradle (do projeto)
serve para ver as configurações do projeto
local onde estão carregadas as bibliotecas que vamos usar
build.gradle (do módulo)
um projeto pode ter vários módulos
versões da compilação do projeto
podem ser alteradas à mão por exemplo as compileSdkVersion e buildToolsVersion
encontramos aqui o applicationId
a versão minima minSdkVersion 22
a versão maxima em que a app vai trabalhar targetSdkVersion 30
a versão da nossa app versionName (pode ser uma string)
>java
devemos apagar e/ou ignorar, não vamos usar nas aulas
androidTest
test
depois voltar ao
>gradle scripts
build.gradle (do módulo)
e apagar:
testInstrumentationRunner “androidx.test.runner.AndroidJUnitRunner”
testImplementation ‘junit:junit:4.+’
androidTestImplementation ‘androidx.test.ext:junit:1.1.2’
androidTestImplementation ‘androidx.test.espresso:espresso-core:3.3.0’
e fazer o sync know
de seguida ver o
>app>manifests>
AndroidManifest.xml
ficheiro que é lido por todos os dispositivos
toda a descrição da app
todos os componentes que a app tem (os quatro): uma nova actividade, um serviço, um content provider, um broadcast receiver (têm que ser registados aqui)
especificar todas as permissões: o que pode usar a app no nosso dispositivo (video, enviar sms, receber sms,…)
coisas no manifest:
icone da app
nome da app
tema da app (formatação)
nome da app pode também ser alterado em app>res>values>strings.xml
suporte da escrita, da direita para a esquerda, supportsRtl
os componentes: <activity android:name=”.MainActivity”>
o <intent-filter>
é para indicar que funcionalidades tem a nossa app para outras apps
ou um atividade para editar imagens, enviar mensagens, fazer pagamentos..



















