How make function to progress bar, for different items in BaseAdapter - java

I used listview. I have 5 items. When I start program I see only 3. Handler what is for progress bar start working for 3/5 items. I go to see 4,5 item, so i lost from view 1,2 item. 4 and 5 item handler starts working.
//Adapter class
var progress = 0
var gain = myData
handler = Handler(Handler.Callback {
progress = progress + speed
if (progress >= 100) {
progress = 0
functionWhatChangeInFirebase(gain)
}
iData.progressBar?.progress = progress
handler?.sendEmptyMessageDelayed(0, 100)
true
})
handler.sendEmptyMessage(0)
Problem is when I go back to look at first and second item, handler start "new thread" and progress bar have more that one function, what changed data.
Edit
Added Adapter class
package com.example.adventurepwr
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Color
import android.os.Handler
import android.support.design.widget.FloatingActionButton
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.ProgressBar
import android.widget.TextView
import android.widget.Toast
import java.util.ArrayList
class AdapterItem(context: Context, private val itemList: ArrayList<Item>) : BaseAdapter() {
private val mInflater: LayoutInflater = LayoutInflater.from(context)
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
val current = itemList[position]
val item: String = current.item!!
val level: Int = current.level!!
val price: Int = current.price!!
val gain: Int = current.gain!!
val speed: Int = current.speed!!
val count: Int = current.count!!
val view: View
val iData: ItemsData
if (convertView == null) {
view = mInflater.inflate(R.layout.content_item, parent, false)
iData = ItemsData(view)
view.tag = iData
} else {
view = convertView
iData = view.tag as ItemsData
}
iData.name?.text = item
iData.level?.text = level.toString()
iData.price?.text = price.toString()
iData.gain?.text = gain.toString()
iData.speed?.text = speed.toString()
iData.count?.text = count.toString()
var progress: Int = 0
var handler: Handler? = null
iData.lvlButton?.setOnClickListener {
canUpgrade(price, item)
}
handler = Handler(Handler.Callback {
progress = progress + speed
if (progress >= 100) {
progress = 0
addMoneyNormal(gain)
}
iData.progressBar?.progress = progress
handler?.sendEmptyMessageDelayed(0, 100)
true
})
handler.sendEmptyMessage(0)
return view
}
override fun getItem(index: Int): Any {
return itemList.get(index)
}
override fun getItemId(index: Int): Long {
return index.toLong()
}
override fun getCount(): Int {
return itemList.size
}
private class ItemsData(row: View?) {
val name: TextView? = row!!.findViewById(R.id.name_item) as TextView?
val level: TextView? = row!!.findViewById(R.id.lvl_Number) as TextView?
val price: TextView? = row!!.findViewById(R.id.price_number) as TextView?
val speed: TextView? = row!!.findViewById(R.id.speed) as TextView?
val gain: TextView? = row!!.findViewById(R.id.gain) as TextView?
val count: TextView? = row!!.findViewById(R.id.count_number) as TextView?
val lvlButton: FloatingActionButton? = row!!.findViewById(R.id.lvl_up_button) as FloatingActionButton?
val progressBar: ProgressBar? = row!!.findViewById(R.id.progressBar) as ProgressBar?
}
}
I go to the main
and do something like this, but i get stackOverflow 8mb
fun progress(){
for (oneRecord in itemList) {
val item: Item = oneRecord
item.count=item.count!! + item.speed!!
if (item.count!!>100){
addMoneyNormal(item.gain!!)
item.count=0
}
Thread.sleep(1000)
}
adapterItem.notifyDataSetChanged()
progress()
}
progress()
Maybe we can do something with this
Now progressBar.progress = count

val myRun = object : Runnable {
override fun run() {
for (oneRecord in mUploads) {
val item: Item = oneRecord
item.count = item.count!! + item.speed!!
if (item.count!! >= 100) {
item.count = 0
addMoneyNormal(item.gain!!)
}
}
adapterItem.notifyDataSetChanged()
this#MainActivity.mHandler.postDelayed(this, 100)
}
}
myRun.run()
So i use this in my main class
in adapter i used, that count is progression
For now I dont see any bugs

Im not sure, but you need to move handler from getView() and you should check for each item.
Can you try this:
fun testMethod(current) {
if(current.count < 4) {
return
}
handler = Handler(Handler.Callback {
progress = progress + speed
if (progress >= 100) {
progress = 0
addMoneyNormal(gain)
}
iData.progressBar?.progress = progress
handler?.sendEmptyMessageDelayed(0, 100)
true
})
handler.sendEmptyMessage(0)
}

Related

How Add Animation On view when view width is changing [Android]

I'm using collapsing toolbar and I am changing view width OnOffsetChangedListener. what I want is that put little animation when searchView width will change , now its changing very straight and its little weird for user. I tried to set android:animateLayoutChanges="true" on parent layout but it not worked
var mListener =
OnOffsetChangedListener { appBarLayout, verticalOffset ->
if (binding.collapsingToolbar.getHeight() + verticalOffset < 2 * ViewCompat.getMinimumHeight(
binding.collapsingToolbar
)
) {
val view: View = binding.searchView
val layoutParams: CollapsingToolbarLayout.LayoutParams = view.layoutParams as CollapsingToolbarLayout.LayoutParams
layoutParams.width = binding.appBar.width / 2
view.layoutParams = layoutParams
} else {
val view: View = binding.searchView
val layoutParams: CollapsingToolbarLayout.LayoutParams = view.layoutParams as CollapsingToolbarLayout.LayoutParams
layoutParams.width = CollapsingToolbarLayout.LayoutParams.MATCH_PARENT
view.layoutParams = layoutParams
}
}
binding.appBar.addOnOffsetChangedListener(mListener)
How you tried built-in interpolators?
Please check below link for some insights:
https://jebware.com/interp/android-animation-interpolators.html
a very basic example is as follows:
val fastOutSlowInInterpolator = FastOutSlowInInterpolator()
val interpolatedValue = fastOutSlowInInterpolator.getInterpolation(0.5f)
In above example 0.5f would vary from 0 to 1 and it will return animated value which you should use in view animation.
You can simply define an animation class.
class ResizeWidthAnimation(private val mView: View, private val mWidth: Int) : Animation() {
private val mStartWidth: Int = mView.width
override fun applyTransformation(interpolatedTime: Float, t: Transformation{
mView.layoutParams.width = mStartWidth + ((mWidth - mStartWidth) * interpolatedTime).toInt()
mView.requestLayout()
}
override fun willChangeBounds(): Boolean {
return true
}
}

How to add animation to the viewPager in Kotlin?

**this is my Activity pager **
private const val TAG = "CarpagerActivity"
var carList: ArrayList<Car>? = null
var mSerializer : JsonSerializer? = null
class CarPagerActivity : AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_car_pager)
mSerializer = JsonSerializer("CarTrinkApp.json",
applicationContext)
try {
carList = mSerializer!!.load()
} catch (e: Exception) {
carList = ArrayList()
Log.e("Error loading cars: ", "", e)
}
// create list of fragments, one fragment for each car
var carFragmentList = java.util.ArrayList<Fragment>()
for (car in carList!!) {
carFragmentList.add(ShowCarFragment.newInstance(car))
}
val pageAdapter = CarPagerAdapter(supportFragmentManager, carFragmentList)
findViewById<ViewPager>(R.id.pager_cars).adapter = pageAdapter
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
val myPost = data?.getIntExtra("adapterPosition", 123)
println(myPost)
println("adadadada")
}
class CarPagerAdapter(fm: FragmentManager, private val carFragmentList: ArrayList<Fragment>) : FragmentPagerAdapter(fm, FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
override fun getCount() = carFragmentList.size
override fun getItem(position: Int) = carFragmentList[position]
}
}
[![I want add animation to this transition ][1]][1]
**and also this page in Fragment Layout **
[1]: https://i.stack.imgur.com/qFB3b.png
Fading animation, see reference here
viewPager.setPageTransformer(false) { page, position ->
// do transformation here
page.alpha = 0f
page.visibility = View.VISIBLE
// Start Animation for a short period of time
page.animate()
.alpha(1f).duration =
page.resources.getInteger(android.R.integer.config_longAnimTime)
.toLong()
}
or
viewPager.setPageTransformer(false) { page, position ->
// do transformation here
page.rotationY = position * -70
}

Custom AppCompatEditText Component not initializing

I'm new to Kotlin and I'm trying to implement a custom pin entry text edit field as done in this tutorial.
I re-wrote the PinEntryEditText in Kotlin, and it throws no errors. I also added to my XML layout file, and used it in my MainActivity page. It runs and throws no errors. However, it does not display as it is supposed to. I started trying to debug it and setup 3 breakpoints on each of the class constructors. The debugger does not stop at any of them, which makes me think it never even goes from there.
Now, here is my class :
class PinEntryEditText : AppCompatEditText {
private var mSpace = 24f //24 dp by default, space between the lines
private var mCharSize: Float = 0.toFloat()
private var mNumChars = 4f
private var mLineSpacing = 8f //8dp by default, height of the text from our lines
private var mMaxLength = 4f
val XML_NAMESPACE_ANDROID = "http://schemas.android.com/apk/res/android"
var mClickListener: View.OnClickListener? = null
private var mLineStroke = 1f //1dp by default
private var mLineStrokeSelected = 2f //2dp by default
private var mLinesPaint: Paint? = null
var mStates = arrayOf(intArrayOf(android.R.attr.state_selected), // selected
intArrayOf(android.R.attr.state_focused), // focused
intArrayOf(-android.R.attr.state_focused))// unfocused
var mColors = intArrayOf(Color.GREEN, Color.BLACK, Color.GRAY)
var mColorStates = ColorStateList(mStates, mColors)
constructor(context: Context) : super(context) {
this.setWillNotDraw(false)
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
this.setWillNotDraw(false)
init(context, attrs)
}
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
this.setWillNotDraw(false)
init(context, attrs)
}
private fun init(context: Context, attrs: AttributeSet) {
val multi = context.resources.displayMetrics.density
mLineStroke = (multi * mLineStroke)
mLineStrokeSelected = (multi * mLineStrokeSelected)
mLinesPaint = Paint(paint)
mLinesPaint?.strokeWidth = mLineStroke.toFloat()
if (!isInEditMode) {
val outValue = TypedValue()
context.theme.resolveAttribute(colorControlActivated,
outValue, true)
val colorActivated = outValue.data
mColors[0] = colorActivated
context.theme.resolveAttribute(colorPrimaryDark,
outValue, true)
val colorDark = outValue.data
mColors[1] = colorDark
context.theme.resolveAttribute(colorControlHighlight,
outValue, true)
val colorHighlight = outValue.data
mColors[2] = colorHighlight
}
setBackgroundResource(0)
mSpace = (multi * mSpace) //convert to pixels for our density
mLineSpacing = (multi * mLineSpacing) //convert to pixels for our density
mMaxLength = attrs.getAttributeIntValue(XML_NAMESPACE_ANDROID, "maxLength", 4).toFloat()
mNumChars = mMaxLength
//Disable copy paste
super.setCustomSelectionActionModeCallback(object : ActionMode.Callback {
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
return false
}
override fun onDestroyActionMode(mode: ActionMode) {}
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
return false
}
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
return false
}
})
// When tapped, move cursor to end of text.
super.setOnClickListener { v ->
setSelection(text!!.length)
if (mClickListener != null) {
mClickListener?.onClick(v)
}
}
}
override fun setOnClickListener(l: View.OnClickListener?) {
mClickListener = l
}
override fun setCustomSelectionActionModeCallback(actionModeCallback: ActionMode.Callback) {
throw RuntimeException("setCustomSelectionActionModeCallback() not supported.")
}
override fun onDraw(canvas: Canvas) {
//super.onDraw(canvas)
val availableWidth = width - paddingRight - paddingLeft
if (mSpace < 0) {
mCharSize = availableWidth / (mNumChars * 2 - 1)
} else {
mCharSize = (availableWidth - mSpace * (mNumChars - 1)) / mNumChars
}
var startX = paddingLeft.toFloat()
val bottom = height - paddingBottom
//Text width
val text = text
val textLength = text!!.length
val textWidths = FloatArray(textLength)
paint.getTextWidths(getText(), 0, textLength, textWidths)
for (i in 0..mNumChars.toInt()) {
updateColorForLines(i == textLength)
canvas.drawLine(startX.toFloat(), bottom.toFloat(), startX.toFloat() + mCharSize, bottom.toFloat(), paint)
if (text.length > i) {
val middle = startX + mCharSize / 2
canvas.drawText(text, i,i + 1, middle - textWidths[0] / 2, (bottom - mLineSpacing).toFloat(), paint)
}
if (mSpace < 0) {
startX += mCharSize * 2
} else {
startX += mCharSize + mSpace
}
}
}
private fun getColorForState(vararg states: Int): Int {
return mColorStates.getColorForState(states, Color.GRAY)
}
private fun updateColorForLines(next: Boolean) {
if (isFocused) {
mLinesPaint?.strokeWidth = mLineStrokeSelected.toFloat()
mLinesPaint?.color = getColorForState(android.R.attr.state_focused)
if (next) {
mLinesPaint?.color = getColorForState(android.R.attr.state_selected)
}
} else {
mLinesPaint?.strokeWidth = mLineStroke.toFloat()
mLinesPaint?.color = getColorForState(-android.R.attr.state_focused)
}
}
}
And here's my XML for the component :
<com.myapp.app.myapp.PinEntryEditText
android:id="#+id/pin_entry_edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:cursorVisible="false"
android:digits="1234567890"
android:inputType="number"
android:maxLength="4"
android:textIsSelectable="false"
android:textSize="20sp" />
Do I have to programmatically assign the class? Unfortunately, I don't really know how to approach this since the debugger won't even step into the class. Any form of input on what could be wrong with this would be greatly appreciated.
# Giulio Colleluori Double check your package name, Your access to the class through package name does not look fine.
According to View.setWillNotDraw, you should remove setWillNotDraw(true) from your constructors:
If this view doesn't do any drawing on its own, set this flag to allow
further optimizations. By default, this flag is not set on View, but
could be set on some View subclasses such as ViewGroup. Typically, if
you override onDraw(android.graphics.Canvas) you should clear this
flag.

PopupWindow Overlap With Virtual Keyboard

I have some problem with showing PopupWindow which is the popup overlaps with the keyboard. here my result
Here my popup code:
class NoteHintList(val view: View, val listener: MenuDetailFragment.OnItemListClickListener?){
var noteHintList: List<String> = ArrayList<String>()
val popupWindow = PopupWindow(view.context)
fun setNoteList(noteHint: List<String>){
this.noteHintList = noteHint
}
// ============ TODO: Pop up note hint ================================================================
fun popupWindow(): PopupWindow {
val popUpContents = arrayOfNulls<String>(noteHintList.size)
ArrayList(noteHintList).toArray(popUpContents)
val listView = ListView(view.context)
listView.adapter = noteHintAdapter(popUpContents)
// set the item click listener
listView.setOnItemClickListener { parent, view, position, id ->
listener!!.onItemListClickListener(listView.getItemAtPosition(position).toString())
}
// val params: LinearLayout.LayoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
// params.setMargins(16,0,16,0)
popupWindow.setFocusable(false)
popupWindow.contentView = view
// popupWindow.setWidth(WindowManager.LayoutParams.MATCH_PARENT - 32)
// popupWindow.setHeight(WindowManager.LayoutParams.WRAP_CONTENT)
popupWindow.setContentView(listView)
return popupWindow
}
// ============ TODO: Popup list adapter for pop up ===================================================
private fun noteHintAdapter(array: Array<String?>): ArrayAdapter<Any> {
return object : ArrayAdapter<Any>(view.context, android.R.layout.simple_list_item_1, array) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
// setting the ID and text for every items in the list
val text = getItem(position)!!.toString()
// visual settings for the list item
val listItem = TextView(context)
listItem.setText(text)
listItem.tag = position
listItem.textSize = 22f
listItem.setPadding(10, 10, 10, 10)
listItem.setTextColor(Color.WHITE)
return listItem
}
}
}
}
The popup will show when text changed. here my code
txtHint.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
val text = txtHint.text.toString()
if (Pattern.compile("^\\s+$").matcher(text).find() || text == "") {
popupNoteHintList!!.setNoteList(noteHintAllList)
} else if (text.split(",").size > 0) {
val textSplit = text.split(",")
val myData = noteHintAllList.filter { s ->
s.toLowerCase().contains(textSplit[textSplit.size - 1].toLowerCase().replace(Regex("^ | \$"), "")) &&
s.toLowerCase() != textSplit[textSplit.size - 1].toLowerCase().replace(Regex("(^ +)|( +$)"), "")
}
popupNoteHintList!!.setNoteList(myData)
if (myData.size > 0) {
popupNoteHintList!!.popupWindow().showAsDropDown(txtHint, 0, 0)
}
}
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
popupNoteHintList!!.popupWindow().dismiss()
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
popupNoteHintList!!.popupWindow().dismiss()
}
})
How to make the popup not overlap with keyboard, maybe move to above EditText if overlap, but still under EditText if not overlap
So result seem like this:
You can hide the soft keyboard in the afterTextChanged method, so that the keyboard is always hidden when your popup appears.
Within the afterTextChanged method, add the following to hide the keyboard:
val imm = getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0) //Hide soft keyboard.

Detect navigation bar visibility

I am trying to check the visibility of the navigation bar. On the Samsung Galaxy S8 I can toggle the navigation bar visibility.
I have tried a lot of different ways to check the visibility, but none of them work on the Galaxy S8.
Some examples: (They will always return the same value, no matter it is shown or hidden)
ViewConfiguration.get(getBaseContext()).hasPermanentMenuKey() always returns false
KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK) always returns false
KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_HOME) always returns true
Even by figuring out the navigation bar height (How do I get the height and width of the Android Navigation Bar programmatically?), it will not work.
Maybe this will be useful for someone. The user can hide the navigation bar, so the best way to detect visibility is to subscribe to this event. It works.
object NavigationBarUtils {
// Location of navigation bar
const val LOCATION_BOTTOM = 0
const val LOCATION_RIGHT = 1
const val LOCATION_LEFT = 2
const val LOCATION_NONE = 3
fun addLocationListener(activity: Activity, listener: (location: Int) -> Unit) {
ViewCompat.setOnApplyWindowInsetsListener(activity.window.decorView) { view, insets ->
val location = when {
insets.systemWindowInsetBottom != 0 -> LOCATION_BOTTOM
insets.systemWindowInsetRight != 0 -> LOCATION_RIGHT
insets.systemWindowInsetLeft != 0 -> LOCATION_LEFT
else -> LOCATION_NONE
}
listener(location)
ViewCompat.onApplyWindowInsets(view, insets)
}
}
}
Since the only answer at the time of writing is Kotlin, here is a Java alternative:
import android.content.res.Resources;
import android.support.v4.view.OnApplyWindowInsetsListener;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.WindowInsetsCompat;
import android.view.View;
public class NavigationBar {
final int BOTTOM = 0;
final int RIGHT = 1;
final int LEFT = 2;
final int NONE = 3;
private int LOCATION = NONE;
private View view;
NavigationBar(View view) {
this.view = view;
}
int getNavBarLocation() {
ViewCompat.setOnApplyWindowInsetsListener(view, new OnApplyWindowInsetsListener() {
public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
if (insets.getSystemWindowInsetBottom() != 0)
LOCATION = BOTTOM;
else if (insets.getSystemWindowInsetRight() != 0)
LOCATION = RIGHT;
else if (insets.getSystemWindowInsetLeft() != 0)
LOCATION = LEFT;
else
LOCATION = NONE;
return insets;
}
});
return LOCATION;
}
int getNavBarHeight() {
Resources resources = view.getResources();
int resourceId = resources.getIdentifier(
"navigation_bar_height", "dimen", "android");
if (resourceId > 0)
return resources.getDimensionPixelSize(resourceId);
return 0;
}
}
I have also included how to get the height, since that will often be the next step.
In your activity, you would then call the methods using a view-based reference:
NavigationBar navigationBar = new NavigationBar(snackbarLayout);
if (navigationBar.getNavBarLocation() == navigationBar.BOTTOM) {
FrameLayout.LayoutParams parentParams =
(FrameLayout.LayoutParams) snackbarLayout.getLayoutParams();
parentParams.setMargins(0, 0, 0, 0 - navigationBar.getNavBarHeight());
snackbarLayout.setLayoutParams(parentParams);
}
(This example is based on a common issue with inconsistent SnackBar margins)

Categories

Resources