I'm learn kotlin and javafx. I'm trying to set up an event.
This java code works:
tableView.setOnKeyPressed(event -> {
TablePosition<?, ?> pos = tableView.getFocusModel().getFocusedCell();
if (pos != null && event.getCode().isLetterKey()) {
tableView.edit(pos.getRow(), pos.getTableColumn());
}
});
The same code in kontlin(not work):
class DynamicTableView : Application() {
#Throws(Exception::class)
override fun start(stage: Stage) {
val tableView = TableView<ObservableList<String>>()
tableView.setEditable(true)
tableView.getSelectionModel().setCellSelectionEnabled(true)
tableView.setOnKeyPressed { event ->
val pos = tableView.focusModel.focusedCell
if (pos != null && event.code.isLetterKey) {
tableView.edit(pos.row, pos.tableColumn)
}
}
Scene scene = new Scene(tableView);
primaryStage.setScene(scene);
primaryStage.setWidth(400);
primaryStage.setHeight(400);
primaryStage.setTitle("test");
primaryStage.show();
}
companion object {
#JvmStatic fun main(args: Array<String>) {
launch(DynamicTableView::class.java)
}
}
}
Kotlin: tableView.edit(pos.row, pos.tableColumn) method tableColumn return the wrong type.
Verbatim: Type inference failed. Expected type mismatch: inferred type is TableColumn <Any!, Any!>! but TableColumn<ObservableList<String>!, *>! was expected
What am i doing wrong?
Maybe you need
tableView.setOnKeyPressed { event ->
val pos = tableView.focusModel.focusedCell
if (pos != null && event.code.isLetterKey) {
tableView.edit(pos.row, tableView.columns[pos.column])
}
}
Related
It successfully shows notifications when the app is open. It shows even when the app is in the background. When I close the app it doesn't show up anymore. I don't want to use FCM. because I want to remember this when doing other applications. In a video, she said that the service above Android 8 does not work permanently, and that startForeground () should be used as a solution for this.But I don't want to use it because it creates a permanent notification on top
class MyFirebaseMessagingService : Service() {
private val channelId = "notification_channel"
private val channelName = "com.dombikpanda.doktarasor.service"
private val notificationTitle = "Sorunuz Cevaplanmıştır"
private val notificationMessage =
"Doktor tarafından sorunuz cevaplanmıştır.Görmek için tıklayınız"
private var importance = 0
private var notifManagerId = 0
override fun onBind(intent: Intent): IBinder? {
return null
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
questionNotification()
return START_STICKY
}
override fun onDestroy() {
super.onDestroy()
}
override fun onCreate() {
createNotifChannel()
super.onCreate()
}
private val crudRepository = CrudRepository()
private fun questionNotification() {
val shared = getSharedPreferences("kontrol", MODE_PRIVATE)
val control = shared.getLong("date", 0)
val collection = Firebase.firestore.collection("questions")
collection
.addSnapshotListener { value, error ->
error.let {
}
value?.let { result ->
for (document in result) {
if (document["userid"] == crudRepository.getFirebaseAuth().uid) {
if (document["cevapdurum"] == true && document["messageDurum"] == true && document["date"] == control) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotification()
}
break
}
}
}
}
}
}
private fun createNotifChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
importance = NotificationManager.IMPORTANCE_HIGH //normal high
val notificationChannel =
NotificationChannel(channelId, channelName, importance).apply {
description = notificationMessage
}
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
manager.createNotificationChannel(notificationChannel)
}
}
#RequiresApi(Build.VERSION_CODES.O)
private fun createNotification() {
val intent = Intent(this, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent =
PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)
val notification = NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.ic_stat_name)
.setContentTitle(notificationTitle)
.setContentText(notificationMessage)
.setAutoCancel(true)
.setOnlyAlertOnce(true)
.setStyle(NotificationCompat.DecoratedCustomViewStyle())
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setVibrate(longArrayOf(1000, 1000, 1000, 1000))
.setSound(Settings.System.DEFAULT_NOTIFICATION_URI)
.setContentIntent(pendingIntent)
with(NotificationManagerCompat.from(this)) {
notify(notifManagerId, notification.build())
notifManagerId++
}
}
}
i want to avoid fragment recreation by using BottomNavigationView
i read about that FragmentTransaction.replace is the problem and changing to add would help, but that didn't work for me..
maybe you can see here where i'm wrong
this is my Host Activity which hosting 3 fragments with BottomNavigationView
'''
class Host : AppCompatActivity() {
var fragment: Fragment? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_host)
//for hide the actionBar (contains Fragment name) on top of the screen
val actionBar = supportActionBar
actionBar?.hide()
val navController = Navigation.findNavController(this, R.id.nav_host_fragment)
val navView = findViewById<BottomNavigationView>(R.id.nav_view)
navView?.setupWithNavController(navController)
NavigationUI.setupWithNavController(navView, navController)
mAdapter = NfcAdapter.getDefaultAdapter(this)
fragmentStayAlive()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
for (fragment in supportFragmentManager.fragments) {
fragment.onActivityResult(requestCode, resultCode, data)
}
}
fun ByteArray.toHexString() = joinToString("") { "%02x".format(it) }
private fun fragmentStayAlive(){
val fragment1: Fragment = LobbyFragment()
val fragment2: Fragment = GameSessionFragment()
val fragment3: Fragment = UserStatusFragment()
val fm: FragmentManager = supportFragmentManager
var active = fragment1
fm.beginTransaction().add(R.id.nav_host_fragment, fragment3, "UserStatusFragment").hide(
fragment3
).commit();
fm.beginTransaction().add(R.id.nav_host_fragment, fragment2, "GameSessionFragment").hide(
fragment2
).commit();
fm.beginTransaction().add(R.id.nav_host_fragment, fragment1, "LobbyFragment").commit();
val mOnNavigationItemSelectedListener: BottomNavigationView.OnNavigationItemSelectedListener =
object : BottomNavigationView.OnNavigationItemSelectedListener {
override fun onNavigationItemSelected(item: MenuItem): Boolean {
when (item.getItemId()) {
R.id.lobbyFragment -> {
fm.beginTransaction().hide(active).show(fragment1).commit()
active = fragment1
return true
}
R.id.gameSessionFragment -> {
fm.beginTransaction().hide(active).show(fragment2).commit()
active = fragment2
return true
}
R.id.userStatusFragment -> {
fm.beginTransaction().hide(active).show(fragment3).commit()
active = fragment3
return true
}
}
replaceFragment(active, null, true, true)
return false
}
}
}
fun replaceFragment(
fragment: Fragment,
#Nullable bundle: Bundle?,
popBackStack: Boolean,
findInStack: Boolean
) {
val fm = supportFragmentManager
val ft: FragmentTransaction = fm.beginTransaction()
val tag = fragment.javaClass.name
val parentFragment: Fragment?
parentFragment = if (findInStack && fm.findFragmentByTag(tag) != null) {
fm.findFragmentByTag(tag)
} else {
fragment
}
// if user passes the #bundle in not null, then can be added to the fragment
if (bundle != null) {
parentFragment!!.arguments = bundle
} else {
parentFragment!!.arguments = null
}
// this is for the very first fragment not to be added into the back stack.
if (popBackStack) {
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
} else {
ft.addToBackStack(parentFragment.javaClass.name + "")
}
ft.add(R.id.nav_view, parentFragment, tag)
ft.commit()
fm.executePendingTransactions()
}
'''
thanks for all the helpers!
I have one activity with 2 recyclerViews, both recyclers are used with Firebase. One of the recyclers displays the results of a query, the other recycler has a listener that updates every time there is an update in Firebase. I added a searchView to filter the results from Firebase. The issue I'm having is when I'm trying to search the results from the Firebase query, when I start typing I see results but when I click the X to stop searching, the adapter does not reload the array and i don't see the list of items unless I reload the activity. I'm not sure what I'm missing here. Any help/suggestion is greatly appreciated. Here is my code:
Adapter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Filter
import android.widget.Filterable
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.eduardoz.ezmdapp.Model.Charges
import com.eduardoz.ezmdapp.R
class ChargesAdapter (private var charges: ArrayList<Charges>
, private var chargesAll: ArrayList<Charges>
, private val itemClick: (Charges) -> Unit)
: RecyclerView.Adapter<ChargesAdapter.ViewHolder>()
, Filterable {
inner class ViewHolder(itemView: View, val itemClick: (Charges) -> Unit) :
RecyclerView.ViewHolder(itemView) {
private val chargeCode = itemView.findViewById<TextView>(R.id.chargeCodeTxt)
private val chargeDescription = itemView.findViewById<TextView>(R.id.chargeDescriptionTxt)
fun bindCharges(charges: Charges) {
chargeCode?.text = charges.chargeCode
chargeDescription?.text = charges.chargeDescription
itemView.setOnClickListener { itemClick(charges) }
}
}
init {
this.charges = charges
chargesAll = java.util.ArrayList(charges)
}
override fun getItemCount(): Int {
return charges.count()
}
override fun onBindViewHolder(holder: ChargesAdapter.ViewHolder, position: Int) {
holder.bindCharges(charges[position])
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChargesAdapter.ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.charges_list, parent, false)
return ViewHolder(view, itemClick)
}
override fun getFilter(): Filter {
return searchFilter
}
private val searchFilter: Filter = object: Filter() {
override fun performFiltering(constraint: CharSequence?): FilterResults {
val filteredList: ArrayList<Charges> = ArrayList()
if (constraint!!.isEmpty()) {
filteredList.addAll(chargesAll)
} else {
for(item in chargesAll) {
if
(item.chargeDescription.toLowerCase().contains(constraint.toString().toLowerCase())) {
filteredList.add(item)
}
}
}
val searchResults = FilterResults()
searchResults.values = filteredList
return searchResults
}
override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
charges.clear()
charges.addAll(results!!.values as Collection<Charges>)
notifyDataSetChanged()
}
}
}
Activity
descriptionSearch.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean {
return false
}
override fun onQueryTextChange(newText: String): Boolean {
if (newText.isNotEmpty()) {
searchViewBar(newText)
} else {
if (newText.isEmpty()) { //I ADDED THIS TO RELOAD THE ADAPTER
charges.clear()
chargeList()
}
}
return false
}
})
private fun searchViewBar(newText: String) {
chargesListener = chargesCollectionRef
.whereGreaterThanOrEqualTo(CHARGE_DESCRIPTION, newText)
.whereLessThanOrEqualTo(CHARGE_DESCRIPTION, newText+"z")
.addSnapshotListener(this) { snapshot, exception ->
if (exception != null) {
println("error")
}
if (snapshot != null) {
charges.clear()
parseData(snapshot)
}
}
}
fun parseData(snapshot: QuerySnapshot) {
for (document in snapshot.documents) {
val data = document.data
val chargeCode = data!![CHARGE_CODE] as String
val chargeDescription = data[CHARGE_DESCRIPTION] as String
val chargeSpecialty = data[CHARGE_SPECIALTY] as String
val newChargeList = Charges(chargeCode, chargeDescription, chargeSpecialty)
charges.add(newChargeList)
}
chargesFromAdapter.notifyDataSetChanged()
}
I am making a children's app where the child can fingerpaint on a book spread as seen below.
The main view is not an ImageView. Rather, it is a custom view extending from GLSurfaceView to allow a pagecurl animation when flipping pages. In order to make a canvas, when a crayon is clicked, my code launches a fragment with a transparent layout to enable drawing on top of the custom view.
It works for each separate color. But when a new color is clicked, the old lines are removed (because a new fragment is launched) and I can draw again using the new color.
However, the ideal behavior is that the old drawing is retained (using the previous color), and the user should be able to keep on drawing with the new color without the fragment being re-launched.
As a test, I've only used the first 3 colors for now.
In the DrawingFragment, I've actually been able to change the color programmatically from the fragment (to CYAN) by calling the method changeColor. However, I still need to get the click event from the Activity that corresponds to each color.
Main Problems:
App should launch the fragment only once on the first instance any
crayon is clicked.
App should identify if the fragment is already created, and if so, pass the button click event from Activity to Fragment each time a crayon is clicked.
I have a vague idea that maybe I should use an interface but I've yet to fully understand what this does. I'm pretty new to kotlin and android and any help or suggestion will be greatly appreciated.
Main Activity
class ReadBooksActivity : Activity() {
var mCurlView: CurlView? = null
var reading_toolbar : View? = null
var isUp = false
var drawColor : Int? = null
var isDrawing = false
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.readbooks_layout)
// Start Page Curl for each page
mCurlView = findViewById(R.id.curl)
mCurlView!!.setSizeChangedObserver(SizeChangedObserver())
mCurlView!!.setCurrentIndex(index)
var bookId = intent.getIntExtra("ID", 0)
Thread(Runnable {
fetchbookpages()
mCurlView!!.setBitmapProvider(BitmapProvider(mBitmaps))
}).start()
mCurlView!!.setEnableTouchPressure(true)
mCurlView!!.set2PagesLandscape(true)
mCurlView!!.setAllowLastPageCurl(true)
// Toggle Reading Toolbar
reading_toolbar = findViewById(R.id.readingtoolbar) as View
// Enable drawing on View
tabtools.setOnClickListener(View.OnClickListener {
showToolbar()
})
tabexit2.setOnClickListener(View.OnClickListener {
hideToolbar()
})
tabexit.setOnClickListener(View.OnClickListener {
onSlideViewButtonClick(reading_toolbar!!)
})
}
fun buttonClicked(view: View) {
//if (!isDrawing) {
if (view.id == R.id.crayon_black) {
drawColor = Color.BLACK
} else if (view.id == R.id.crayon_blue) {
drawColor = Color.BLUE
} else if (view.id == R.id.crayon_green) {
drawColor = Color.GREEN
}
callDrawFragment(drawColor!!)
// }
// isDrawing = true
}
fun callDrawFragment(drawColor : Int) {
val mFragment = DrawingFragment.newInstance(drawColor)
fragmentManager!!
.beginTransaction()
.replace(R.id.mainreadinglayout, mFragment)
.addToBackStack(null)
.commit()
}
}
DrawingFragment
class DrawingFragment: Fragment() {
var drawColor : Int? = null
var drawingView : DrawingView? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.drawing_layout, container, false)
val relativeLayout = view.findViewById(R.id.draw_layout) as RelativeLayout
drawColor = arguments.getInt("color")
var drawingView = DrawingView(activity, drawColor!!)
relativeLayout.addView(drawingView)
changeColor(drawingView)
return view
}
fun changeColor(view: DrawingView) {
var currentPaint = Paint()
currentPaint.setColor(Color.CYAN)
currentPaint.isAntiAlias = true
currentPaint.isDither = true
currentPaint.style = Paint.Style.STROKE
currentPaint.strokeJoin = Paint.Join.ROUND
currentPaint.strokeCap = Paint.Cap.ROUND
currentPaint.strokeWidth = 10f
view.setPaint(currentPaint)
}
companion object {
fun newInstance(color: Int): DrawingFragment {
val args = Bundle()
args.putInt("color", color)
val fragment = DrawingFragment()
fragment.arguments = args
return fragment
}
}
}
DrawingView
class DrawingView(context: Context, color : Int) : View(context) {
var mPaint: Paint? = null
val mPath: Path
init {
mPaint = Paint()
mPaint!!.isAntiAlias = true
mPaint!!.isDither = true
mPaint!!.color = color
mPaint!!.style = Paint.Style.STROKE
mPaint!!.strokeJoin = Paint.Join.ROUND
mPaint!!.strokeCap = Paint.Cap.ROUND
mPaint!!.strokeWidth = 10f
mPath = Path()
}
override fun onDraw(canvas: Canvas) {
canvas.drawPath(mPath, mPaint)
super.onDraw(canvas)
canvas.drawColor(Color.TRANSPARENT)
}
fun setPaint(mPaint: Paint) {
this.mPaint = mPaint
return
}
override fun onTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> mPath.moveTo(event.x, event.y)
MotionEvent.ACTION_MOVE -> {
mPath.lineTo(event.x, event.y)
invalidate()
}
MotionEvent.ACTION_UP -> {
}
}
return true
}
}
I figured this out by referencing the activity's buttons from the fragment.
var btn_black = (getActivity()).findViewById(R.id.crayon_black) as ImageView
var btn_blue = (getActivity()).findViewById(R.id.crayon_blue) as ImageView
var btn_green = (getActivity()).findViewById(R.id.crayon_green) as ImageView
And then setting the onclick listeners in the fragment
btn_black.setOnClickListener(View.OnClickListener {
changeColor(drawingView, Color.BLACK)
})
btn_blue.setOnClickListener(View.OnClickListener {
changeColor(drawingView, Color.BLUE)
})
btn_green.setOnClickListener(View.OnClickListener {
changeColor(drawingView, Color.GREEN)
})
And then re-setting the onclicklisteners on the activity on backpressed. I also had a booleanTag to indicate if the fragment is up or not.
override fun onBackPressed() {
setColorOnClickListeners()
booleanTag = "false"
crayon_black.setTag(booleanTag)
if (mCurlView!!.getIsUp()) {
slideDown(reading_toolbar!!)
mCurlView!!.setIsUp(!isUp)
}
super.onBackPressed()
}
The setcolorOnClicklistener() is as follows:
fun setColorOnClickListeners() {
crayon_black.setOnClickListener(View.OnClickListener {
buttonClicked(crayon_black)
})
crayon_blue.setOnClickListener(View.OnClickListener {
buttonClicked(crayon_blue)
})
// etc...
}
buttonClicked:
fun buttonClicked(view: View) {
booleanTag = crayon_black.tag as String
if (booleanTag == "false") {
if (view.id == R.id.crayon_black) {
drawColor = Color.BLACK
} else if (view.id == R.id.crayon_blue) {
drawColor = Color.BLUE
} else if (view.id == R.id.crayon_green) {
drawColor = Color.GREEN
} else if (view.id == R.id.crayon_orange) {
drawColor = Color.parseColor("#FFA500")
} else if (view.id == R.id.crayon_pink) {
drawColor = Color.parseColor("#ec5db8")
} else if (view.id == R.id.crayon_red) {
drawColor = Color.RED
} else if (view.id == R.id.crayon_violet) {
drawColor = Color.parseColor("#8862ba")
} else if (view.id == R.id.crayon_white) {
drawColor = Color.WHITE
} else if (view.id == R.id.crayon_yellow) {
drawColor = Color.YELLOW
}
callDrawFragment(drawColor!!)
booleanTag = "true"
crayon_black.setTag(booleanTag)
}
}
Still need to handle some things on the DrawingView for the color change but this solved most of my problems.
I have cursor returned by an SQLite query, I would like to know correct approach for creating an Observable the emits each row in the cursor.
I created cursor observable as follows, please check if this is the correct:
Observable<Cursor> cursorObservable = Observable.create(new ObservableOnSubscribe<Cursor>() {
#Override
public void subscribe(ObservableEmitter<Cursor> e) throws Exception {
SQLDbHelper dbHelper = SQLDbHelper.getInstance(ctx);
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("select * from " + MoviesContract.MovieEntry.TABLE_NAME, null);
if (cursor != null) {
try {
while (cursor.moveToNext() && !e.isDisposed()) {
e.onNext(cursor);
}
} catch (Exception exception) {
e.onError(exception);
} finally {
cursor.close();
}
}
if (!e.isDisposed()) {
e.onComplete();
}
}
});
I thank that you will have better results wrapping the rows into a Map and passing it through the stream than passing cursor itself.
class SimpleTest {
#Test
fun testCursorStream() {
val cursor = fakeCursor()
val stream = getCursorStream(cursor)
stream.subscribe {
Log.d("Test", it.entries.toString())
}
}
private fun fakeCursor() : Cursor {
val columns = arrayOf("id", "name", "age")
val cursor = MatrixCursor(columns)
val row1 = arrayOf(1, "Rodrigo", 26L)
val row2 = arrayOf(2, "Lucas", 23L)
val row3 = arrayOf(3, "Alan", 26L)
cursor.addRow(row1)
cursor.addRow(row2)
cursor.addRow(row3)
return cursor
}
private fun getCursorStream(cursor: Cursor) : Observable<Map<String, Any?>> {
return Observable.create<Map<String, Any?>> {
try {
if (!cursor.moveToFirst()) {
it.onCompleted()
return#create
}
val row = HashMap<String, Any?>()
do {
val lastColumnIndex = cursor.columnCount - 1
for (index in 0..lastColumnIndex) {
val name = cursor.getColumnName(index)
val type = cursor.getType(index)
when (type) {
Cursor.FIELD_TYPE_STRING -> row.put(name, cursor.getString(index))
Cursor.FIELD_TYPE_BLOB -> row.put(name, cursor.getBlob(index))
Cursor.FIELD_TYPE_FLOAT -> row.put(name, cursor.getFloat(index))
Cursor.FIELD_TYPE_INTEGER -> row.put(name, cursor.getInt(index))
Cursor.FIELD_TYPE_NULL -> row.put(name, null)
}
}
it.onNext(row)
} while (cursor.moveToNext())
it.onCompleted()
} catch (e: Exception) {
it.onError(e)
}
}
}
}
Hope that it helps.