Tag: arquitecturas móveis (kotlin)

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>
Tags : , , , , , ,

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..

Tags : , , , , , ,

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()

    }
}
Tags : , , , , , ,

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
}
...

Tags : , , , , ,

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&lt;Pais&gt;()
        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 -&gt;
            Log.i(TAG, "Item: $pos $id")

        }
    }

    //adapter personalizado derivado do BaseAdapter
    class MyAdapter(val data : ArrayList&lt;Pais&gt;) : 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&lt;TextView&gt;(R.id.tv1).text = data[position].nome
            //usar o tv1 e tv2 para inserir os dados
            view.findViewById&lt;TextView&gt;(R.id.tv2).apply {
                text = data[position].habitantes.toString()
                //filtro dos dados dependendo das cores
                if (data[position].habitantes &gt; 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&lt;ImageView&gt;(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
}
...

Tags : , , , , ,

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
}
...

Tags : , , , , ,

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
}
...

Tags : , , , , ,

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
}
...

Tags : , , , , ,

em kotlin: uma calculadora

Construir 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="&lt;style&gt;" title="&lt;style&gt;" />
</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>
Tags : , , , , ,