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

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

 

 

 

 

 

 

Tags : , ,