I am writing a simple app that changes the application background randomly on button click.
I have a arraylist that contains 5 id's of images that the application should use:
ArrayList<Integer> imageID = new ArrayList<Integer>();
imageID.add(R.drawable.frame_blue);
imageID.add(R.drawable.frame_green);
imageID.add(R.drawable.frame_lilac);
imageID.add(R.drawable.frame_pink);
imageID.add(R.drawable.frame_yellow);
I have two buttons in my layout xml file for next and previous. Both should change Application background when clicked.
I change the image background from this arraylist:
iM.setBackgroundResource(imageID.get(r.nextInt(5)));
and my layout xml looks like:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/parentLayout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginBottom="76dp"
android:onClick="previous"
android:text="Previous" />
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/button1"
android:layout_alignBottom="#+id/button1"
android:layout_alignParentRight="true"
android:onClick="next"
android:text="Next" />
</RelativeLayout>
All works fine on button click's, ImageView background change as I expect, but the problem is the background is not changing smoothly.
It hangs some time. May be the main ui thread will be block for 1 or 2 second and this look like application hangs.
Hangs mean: Some time button remain clicked for a few seconds.
I tried asynctask did not have success. Is there a way to make it change smoothly?
you need to use caching in order to save time and not inflate every time the images
like this : Drawable image_frame_green = getResources().getDrawable(
R.drawable.frame_green);
Have you tried to preload all drawables in cache and then instead of setting the background resource, set the background drawable as background directly.
Related
I have two Buttons nested in a LinearLayout. Between these Buttons are two TextViews. In the Xml, I have set the foreground to an image for each of these Buttons.
It runs fine on my device for Api 23. But on other devices below Api 23, the foreground image does not display and instead results in a default white solid color. Is there any way to make these images show using foreground below Api 23?
We have tried FrameLayout but it does not do what we want it to do. Would ImageButtons be a better way to solve this issue?
One of the core functions of our app is that every time a user taps a Button, the size increases and the image stretches accordingly. This is done dynamically in code. If I were to use ImageButtons, I would need to set the layout parameters every time for height and width, rather than one line of code that sets the height.
Any tips would be appreciated!
EDIT: Code I am working with -
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="11"
android:background="#android:color/black">
<Button
android:layout_weight="5"
android:id="#+id/firstP"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:foreground="#drawable/icebutton"
android:scaleX="1"
android:scaleY="1"/>
<TextView
android:layout_weight="0.5"
android:id="#+id/firstPlayer"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:rotation="180"
android:textColor="#android:color/white"
android:background="#android:color/transparent"/>
<TextView
android:layout_weight="0.5"
android:id="#+id/secondPlayer"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#android:color/white"
android:background="#android:color/transparent"/>
<Button
android:layout_weight="5"
android:id="#+id/secondP"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:foreground="#drawable/firebutton"
android:scaleX="1"
android:scaleY="1"/>
</LinearLayout>
We found out that there were two issues causing the images to not be shown.
1. The size of the image file was too big, creating an outOfMemory error which in turn resulted in the buttons not displaying the images.
2. The foreground attribute does not work for API 22 and below.
Steps to solving these issues:
1. We reduced the size of the image files.
2. We replaced Button with ImageButton
3. In the XML file we removed the foreground attribute, added a black background, and added the image via the src attribute. The following is a snippet.
<ImageButton
android:layout_weight="5"
android:id="#+id/firstP"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:src="#drawable/icebutton"
android:scaleType="fitXY"
android:background="#android:color/black"/>
We then had to change our code to dynamically adjust the height of the buttons to match the new image buttons with the help of this link by setting the LayoutParams:
how to change size of button dynamic in android
Now everything works perfectly!
The target I need to achieve: 2 lines of text and 1 straight line in between should always be on top of Button. So in such a case, setting text in Button's attribute is not applicable according to my knowledge. Therefore I use TextView and View aligning on top of Button to achieve it.
Problem: A strange UI appearance I have come across of Android 5.0+ is that when the Button is enabled, it covers TextView and View even it comes before TextView in RelativeLayout xml file. (according to my knowledge, this means that TextView should on top of Button) The following is my xml code:
<RelativeLayout
android:id="#+id/rl_daily_check_in_button_container"
android:layout_width="140dp"
android:layout_height="140dp"
android:layout_marginBottom="4dp"
android:layout_centerHorizontal="true"
android:layout_above="#+id/textview_check_in_days_in_row">
<Button
android:id="#+id/button_daily_check_in"
android:layout_width="140dp"
android:layout_height="140dp"
android:background="#drawable/daily_checkin_button" />
<TextView
android:id="#+id/textview_check_in"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_above="#+id/view_line"
android:layout_marginBottom="4dp"
android:text="#string/title_not_yet_daily_check_in"
android:textColor="#color/text_gray"
android:textStyle="bold"
android:textSize="36sp" />
<View
android:id="#+id/view_line"
android:layout_width="94dp"
android:layout_height="1dp"
android:layout_centerHorizontal="true"
android:layout_above="#+id/textview_check_in_points"
android:layout_marginBottom="6dp"
android:background="#color/text_gray" />
<TextView
android:id="#+id/textview_check_in_points"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="32dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:text="#string/points_can_get_daily_check_in_placeholder"
android:textColor="#color/text_gray"
android:textSize="14sp" />
</RelativeLayout>
But when the app is in Android 5.0-, say 4.4.2, the UI is exactly what I expect. I have tried to set android:elevation="xxdp" attribute, it success until I set the background of Button programatically. Can anyone explain the reason and how the Andoird 5.0+ render its UI? Many Thanks!
Button on Andoird 5.0+:
Button on Android 5.0-:
From Android Lollipop (5.0), the Button has a default StateListAnimator. It has set the default android:elevation and android:translationZ attributes to the Button. Since the Button has default elevation set to it, it appears above the other Views that doesn't have elevation set (Views that has elevation less than the Button, to be precise). i.e. The Views that has higher elevation set to it will appear above the Views that has lower elevation set.
So that's why, when you changed the Button to ImageView, the problem is solved, because ImageView has no default elevation set.
Issue
I've got an issue with 2 ImageViews on Android.
The first displays a large image. It is inside a RelativeLayout, and is a custom ImageView (com.ortiz.touch). It was displaying well until now.
The second is also inside the RelativeLayout but is a "normal" ImageView. It shows bluetooth state. Displaying it doesn't cause any issue.
However, when I put code that changes the src of the bluetooth indicator programatically, the first image is not displayed anymore ....
Is the problem coming from the custom view not doing its job right ? Am I missing something ?
Code
If I'm not doing this kind of stuff :
bluetoothState.setImageResource(R.drawable.bluetooth_enabled192);
The image is displayed correctly.
Here's the layout I use :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#1b1b1b"
android:theme="#style/Theme.AppCompat.Light.NoActionBar.FullScreen">
<com.ortiz.touch.TouchImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/imageView"
android:layout_gravity="center"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_above="#+id/textView" />
<TextView
android:layout_width="fill_parent"
android:layout_height="32dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="#string/emptyDisplayText"
android:layout_gravity="center_horizontal|bottom"
android:gravity="center_vertical|center_horizontal"
android:textAllCaps="true"
android:elegantTextHeight="false"
android:ellipsize="end"
android:maxLines="1"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:textSize="15sp"
android:textColor="#f3f3f3"
android:id="#+id/textView"
android:background="#drawable/rounded_rect"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="true"
android:layout_margin="10dp" />
<ImageView
android:layout_width="52dp"
android:layout_height="52dp"
android:id="#+id/bluetooth_state"
android:scaleType="centerCrop"
android:layout_alignParentTop="true"
android:layout_alignRight="#+id/textView"
android:layout_alignEnd="#+id/textView"
android:layout_gravity="top|right"
android:layout_margin="10dp"/>
</RelativeLayout>
Desired Result
What I get is the same screen without the central image (the text and bluetooth indication are displayed correctly)
NB
I'm starting to get quite depressed on that issue. I just want to display 2 images. Thank you.
Edit
I've not mentioned it, but the main image is loaded in background, using an AsyncTask. I've tried to add some View.invalidate() (on top level layout, on image, on bluetooth indication) but it hasn't solved the problem.
In addition to the image appearing on rotation, it also appears when I try to pinch the non-existant image. And trying to reset the zoom (hacky) programatically doesn't work either.
Okay I've found the error.
As I said, I have a AsyncTask (BitmapWorkerTask) that I call to load a Bitmap into an ImageView in background.
It's called like this :
new BitmapWorkerTask(imageView, getApplicationContext()).execute(filename);
Changing getApplicationContext() to MainActivity.this or getContext() solves the issue :/ (However, I still find it's quite magic how it worked fine for so long even if application context != activity context !)
I've got a single lined TextView with a text in it that is too long to be displayed at once. Now I want the app to scroll horizontally smoothly to a certain position in the text when the user does certain things. So the scrolling is initiated by user actions but the user doesn't decide himself to which position the app will scroll (so I don't want to implement usual scrolling by swiping). I'd like to have a function scrollTo(int position) which accomplishes the scrolling.
Use an EditText and animate the selection property. You can easily style it to behave like a TextView if that's important, for instance:
<EditText
android:enabled="false"
android:background="#null"
android:textColor="#android:color/black"
android:id="#+id/ttt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="very long text"
android:singleLine="true"/>
And then use property animation to scroll smoothly:
ObjectAnimator anim = ObjectAnimator.ofInt(yourEditText, "selection", from, to);
anim.setDuration(duration);
anim.start();
Note that you should not use a hard coded color for the text because on some phones the background might be different (too dark, for instance). If you have your own theme or using Holo light it you're good, but you should be aware of a possible problem.
Use this code
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/horizontalScrollView1"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text=" This post will help to share your urls and text values into social networks like facebook,twitter and linkedin.in facebook we have to share your urls only, but twitter and linkedin able to share both urls and text." />
</LinearLayout>
I have a Button that is defined in a RelativeLayout as follows:
<Button
android:id="#+id/search_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/current_location"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:paddingBottom="30dp"
android:paddingTop="30dp"
android:text="#string/search" />
I would like to add a ProgressBar behind the Button that occupies the exact same space as the Button, so that when the button is disabled (translucent), you can see the progress bar behind it. How would I do this?
To do this I had to define the button in my main.xml first, followed by the progress bar as follows:
<Button
android:id="#+id/search_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/current_location"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:paddingBottom="30dp"
android:paddingTop="30dp"
android:text="#string/search" />
<ProgressBar
android:id="#+id/cooldown_bar"
style="#android:style/Widget.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="#id/search_button"
android:layout_below="#id/current_location"
android:layout_marginBottom="6dp"
android:layout_marginLeft="9dp"
android:layout_marginRight="9dp"
android:layout_marginTop="1dp"
android:indeterminate="false"
android:progressDrawable="#drawable/progress_bar" />
Then, once I had initialized all the GUI components, I had to bring the button back in front of the progress bar with:
searchButton.bringToFront();
The end result
Button when enabled:
Button when disabled with progress bar:
put this right before the button inside the relative layout in your xml:
<ProgressBar
android:id="#+id/descriptive_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/current_location"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:paddingBottom="30dp"
android:paddingTop="30dp"
/>
by using all of the same layotu and padding attributes we can make sure the View will be in the same spot and roughly the same size (height could be different because of wrap_content) I think if you put the progress bar first in the layout file then the button should appear on top.
But also you can enforce whatever policy you want with view.setVisibility(visibility-ness)just make sure whenever you make one visible you make the other invisible.
that way in-case I am wrong about how they stack by default based on their position in the file (which I could be, I didn't verify it just now) and in the event you don't want to move the progress bar to bellow the button in the file, you could still achieve the same thing from the users perspective.