howTo get Image Resource of a ImageButton in kotlin - kotlin

i want change the ImageResource of a ImageButton that i have find by id.
Motivation
a ImageButton(bottom) works as a reminder/backup of the last click of a ImageButton(top) .
setup:
some ImageButton (at the top of the app).
a ImageButton (at the bottom of the app).
example without errors, but don't find ImageResource of idR1
findViewById<ImageButton>(idR1).setOnClickListener {
findViewById<ImageButton>(idR5_oppCiv).setImageResource(R.drawable.athen_cavalry_swordsman);
not working examples
findViewById<ImageButton>(idR1).setOnClickListener {
findViewById<ImageButton>(idR5_oppCiv).setImageResource(it.resources.getDrawable());
findViewById<ImageButton>(idR1).setOnClickListener {
findViewById<ImageButton>(idR5_oppCiv).setImageResource(it.getImageResource());
try to get and set Drawable
following causes the app to crash when i click on an ImageButton.
Here i use a defType "res" to get the resource (the image hopefully).
val resR1: Int = resources.getIdentifier("r1col$i", "res", this.packageName)
findViewById<ImageButton>(idR1).setOnClickListener {
findViewById<ImageButton>(idR5_oppCiv).setImageDrawable(getDrawable(resR1))
How could i get this image resource of it ? And use it for the other ImageButton?

You should be setting the image like using setImageDrawable like this.
val image = findViewById<ImageButton>(R.id.your_view_id)
image.setOnClickListener {
findViewById<ImageButton>(idR5_oppCiv).setImageDrawable(image.drawable)
}

Related

Custom CollapsingTopAppBar Jetpack Compose

The essence of the problem is that I want to write my own version of the AppBar that would include content as another Compose function. After looking at the source code of the current CollapsingTopAppBar implementation, I saw the following lines:
#Composable
private fun TwoRowsTopAppBar(
...
scrollBehavior: TopAppBarScrollBehavior?
) {
...
val pinnedHeightPx: Float = 64.dp
val maxHeightPx: Float = 152.dp
LocalDensity.current.run {
pinnedHeightPx = pinnedHeight.toPx()
maxHeightPx = maxHeight.toPx()
}
// Sets the app bar's height offset limit to hide just the bottom title area and keep top title
// visible when collapsed.
SideEffect {
if (scrollBehavior?.state?.heightOffsetLimit != pinnedHeightPx - maxHeightPx) {
scrollBehavior?.state?.heightOffsetLimit = pinnedHeightPx - maxHeightPx
}
}
...
Surface(...) {
Column {
TopAppBarLayout(
...
heightPx = pinnedHeightPx
...
)
TopAppBarLayout(
...
heightPx = maxHeightPx - pinnedHeightPx + (scrollBehavior?.state?.heightOffset
?: 0f),
...
)
}
}
}
As I understand it, scrollBehavior is used to handle the collapse and expansion behavior. In the current implementation, just constant values are put in heightOffsetLimit. And since I need my appbar implementation to be able to contain content of any size, I need to somehow know the size of this content in advance and put this value in heightOffsetLimit.
I have already written the code for my AppBar, so that it also contains content. But since I can't pass the height value of the content to scrollBehavior, the AppBar doesn't collapse to the end.
you need to calculate the height that the appbar will have before drawing it into the screen. I have followed this issue and solved my problem with the last solution. hope it helps:
Get height of element Jetpack Compose
use the content you can put (ex. an image or a huge text) as the MainContent
use your appbar as the DependentContent and use the size given in lambda to give the height to your appbar
finally set placeMainContent false as I believe you don't need to draw the image (or any other composable) directly in a box
and you will good to go

How to change the fonts of all items on recyclerview runtime

I wanted to change font family of items on a recycler view every time I click a button.
So I coded like below.
rbAritaBuri = view.findViewById(R.id.rb_aritaBuri)
rbCafe24 = view.findViewById(R.id.rb_cafe24SurroundAir)
rbAritaBuri.setOnClickListener {
rv_work_preview.tv_work_content.typeface = Typeface.createFromAsset(requireActivity().assets, "fonts/arita_buri.otf")
}
rbCafe24.setOnClickListener {
rv_work_preview.tv_work_content.typeface = Typeface.createFromAsset(requireActivity().assets, "fonts/cafe24_surround_air.ttf")
}
But it changes only the font family of the first item of the recycler view.
Is there a way to change fonts of them all together runtime? And please tell me why the code I wrote doesn't work right.
Thank you.
If I were in your position, I would:
Put your font changing calls inside of onBindViewHolder(). If you have to, you could put a bool in there like buttonClicked and link its value to your buttons.
Come up with a good way to force a call to onBindViewHolder(). Sometimes notifyDataSetChanged() is enough. But in some cases, you might have to remove the adapter by setting it to null and then reset the adapter to its original value.
Place that logic from step 2 inside of your buttons' onClick()s.
Edit:
What I mean is, create a var inside the class with the most exterior scope, so outside of oncreate().
var textChoice=""
Now use your buttons to change that var.
rbAritaBuri.setOnClickListener {
textChoice="fonts/arita_buri.otf"
}
Now inside your onBindViewHolder(), make the font switch.
when (fontChoice){
"fonts/arita_buri.otf"->{ rv_work_preview.tv_work_content.typeface = Typeface.createFromAsset(requireActivity().assets, "fonts/arita_buri.otf")}
//and so on and so forth for all of your fonts
Now when you want to show the change, call notifyDatasetChanged(). I think maybe the best place to do that would be inside of your buttons. So maybe you'd actually have:
rbAritaBuri.setOnClickListener {
textChoice="fonts/arita_buri.otf"
<The name of your recyclerview adapter>.notifyDatasetChanged()
}
Here is how I solved it, thanks to D. Kupra:
class SampleWorkAdapter(private val context: Context) :
RecyclerView.Adapter<SampleWorkAdapter.ViewHolder>() {
var selectedFont = EditTextActivity.HAMBAK_SNOW
First, I assigned the default font Hambak_snow to selectedFont, type String.
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
...
fun changeFont(font: String) {
CustomFontHelper.setCustomFont(content, font, itemView.context)
} ...
}
Then I wrote a function to be called on onBindViewHolder to change font-family of textview, using custom typeface. https://stackoverflow.com/a/16648457/15096801 This post helped a lot.
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
...
viewHolder.changeFont(selectedFont)
...
}
Now, replaceFont will be called when the variable selectedFont get changed and adapter.notifyDatasetChanged() is called on an activity, like this:
rbMapoFlowerIsland.setOnClickListener {
sampleWorkAdapter.selectedFont = EditTextActivity.MAPO_FLOWER
sampleWorkAdapter.notifyDataSetChanged()
}

talkback not focusing by default on any view on start of inner fragment

I am using accessibility talkback functionality and I am facing one problem I have one bottom navigation in the parent activity and from the setting tab I am opening another fragment(inner fragment) using .add but the inner fragment view not getting focus by default
I also tried with . replace but it's not focusing by default on fragment creation.
open fragment code
val details = DetailsFragment.newInstance();
getSupportFragmentManager().setupForAccessibility()
getSupportFragmentManager().beginTransaction().add(android.R.id.content, details).commit()
and I used this extension function to not get focus on the previous fragment from this source
fun FragmentManager.setupForAccessibility() {
addOnBackStackChangedListener {
val lastFragmentWithView = fragments.lastOrNull { it.view != null }
for (fragment in fragments) {
if (fragment == lastFragmentWithView) {
fragment.view?.importantForAccessibility =
View.IMPORTANT_FOR_ACCESSIBILITY_YES
} else {
fragment.view?.importantForAccessibility =
View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
}
}
}
}
in normal I show that at the start of the first fragment it's focusing top first Textview and speaking automatic but in the inner fragment it's not focusing by default so what should I do to get focus by default on the first view by default
I already try
android:focusable="true"
android:focusableInTouchMode="true"
and request focus but it's not working
Please suggest me any help would be highly appriciated
I've had the best luck using
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)
on the view you want to focus, or maybe
Handler().postDelayed({
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)
}, someDelayMillis)
to let the system do whatever it does, and then jump in after a moment and force a focus change.
But this might be considered bad accessibility, if it's interfering with the usual navigation, and that might be why it's so hard to get focus working consistently! It might be better to just announce the new fragment (with something like view.announceForAccessibility("new fragment")) and let the user start navigating from the top. It depends on your app, it's your call
Also you probably want to use replace for your fragment instead of add, if you add a fragment on top of an old one, TalkBack can get stuck looking at the "invisible" views on the old fragment
this is my improved code that extends from #cactustictacs
//target to specific a view
binding.getRoot().postDelayed(new Runnable() {
#Override
public void run() {
binding.textView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
}
}, 300);
full: https://github.com/dotrinh-PM/AndroidTalkback

Change JavaFX TabPane background

I'm developing an application in javaFx and I'm using TabPane to organise content. My problem is that when I put a node as the content of a tab, and then set the background of that same node, the background color gets kind of blurry, as you can see in the image, the background color was defined in a css file.
If anyone knows how to resolve this, would really appreciate the help.
http://i.stack.imgur.com/h3gNH.png
I think you are a victim of this issue:
JavaFX Image (PNG) transparency crispness being lost when rendering
It will likely be fixed in a forthcoming (i.e. Java 8) release.
For now, you may be able to use the work-around documented in the linked question's answer.
To do this, place your image in a CenteredRegion and use that as the first element of a StackPane placed in your tab. Then layer the rest of the tab content over the image by adding the content to the StackPane. It's a bit awkward and there may be a more straight-forward solution for your particular case.
class CenteredRegion extends Region {
private Node content;
CenteredRegion(Node content) {
this.content = content;
getChildren().add(content);
}
#Override protected void layoutChildren() {
content.relocate(
Math.round(getWidth() / 2 - content.prefWidth(USE_PREF_SIZE) / 2),
Math.round(getHeight() / 2 - content.prefHeight(USE_PREF_SIZE) / 2)
);
}
public Node getContent() {
return content;
}
}

animation for zoom in and zoom out in android for imageview

How do i set zoom in and zoom out when click on imageview?I want my program to react when user click on imageview must get large to some extent and can move imageview on that screen and sometime it reduce the size along when it move on touch anywhere on the screen .when click again is go resume original size what do i do?
As far as I know there are two ways.
The first way:
Make a new folder in res called 'anim'. Than make a xml file inside, for example zoomin.xml. Afterwards put the following code inside.
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="1"
android:toXScale="5"
android:fromYScale="1"
android:toYScale="5"
android:pivotX="50%"
android:pivotY="50%"
android:duration="1000"
android:fillAfter="true">
</scale>
Make another one for zoom out, but with reversed values.
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="5"
android:toXScale="1"
android:fromYScale="5"
android:toYScale="1"
android:pivotX="50%"
android:pivotY="50%"
android:duration="1000"
android:fillAfter="true">
</scale>
You can change the values according to your needs. I think that they are self-explanatory.
And now in your java code.
ImageView imageView = (imageView)findViewById(R.id.yourImageViewId);
Animation zoomin = AnimationUtils.loadAnimation(this, R.anim.zoomin);
Animation zoomout = AnimationUtils.loadAnimation(this, R.anim.zoomout);
imageView.setAnimation(zoomin);
imageView.setAnimation(zoomout);
Now you only need to keep track which is the current state. And for each state execute this lines of codes:
imageView.startAnimation(zoomin);
and
imageView.startAnimation(zoomout);
For example:
imageView.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
if(!pressed) {
v.startAnimation(zoomin);
pressed = !pressed;
} else {
v.startAnimation(zoomout);
pressed = !pressed;
}
}
});
The other way is described here : http://developer.android.com/training/animation/zoom.html.
You can make this by following this guide easily
http://developer.android.com/training/animation/zoom.html
shortly you should use third imageview which is invisible when the user touches any imageview you want, you can display it by using animation in the imageview which is invisible.