By default HorizontalScrollView scrolls from Left to Right but I want to scroll from Right to Left.
How to do this? Any help will be appreciated.
You can scroll it to the right edge of your scroll view in your code with something like this:
scrollView.postDelayed(new Runnable() {
public void run() {
scrollView.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
}
}, 100L);
Related Q and A is https://stackoverflow.com/a/4720563/2511775
add layout_gravity RIGHT its helpful when items dose not wrap hole with
<HorizontalScrollView
android:id="#+id/scrollPartition"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none">
<LinearLayout
android:id="#+id/lytPartition"
android:layout_gravity="right"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:scrollbars="none">
</LinearLayout>
</HorizontalScrollView>
and in code need to scroll to the end of list
findViewById(R.id.scrollPartition).post(new Runnable() {
#Override
public void run() {
((HorizontalScrollView) findViewById(R.id.scrollPartition)).fullScroll(View.FOCUS_RIGHT);
}
});
to set layout_gravity programmatically use this :
HorizontalScrollView scrollView = new HorizontalScrollView(context);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.gravity = Gravity.RIGHT;
scrollView.setLayoutParams(layoutParams);
Add this attribute to HorizontalScrollView :
android:layoutDirection="rtl"
(not good solution)
Related
I am creating a game and I have assigned three image views of (balls) at the top of my screen and code an animation for them. The balls are going down to the bottom from the top, but I want the balls from the top of the screen to not show at the start of the animation... any advice?
Here is the relevant Activity code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ball1 = (ImageView) findViewById(R.id.ball1);
ball2 = (ImageView) findViewById(R.id.ball2);
ball3 = (ImageView) findViewById(R.id.ball3);
}
private void startBallAnimation() {
final TranslateAnimation animation = new TranslateAnimation(
TranslateAnimation.RELATIVE_TO_PARENT, 0.0f,
TranslateAnimation.RELATIVE_TO_PARENT, 0.0f,
TranslateAnimation.RELATIVE_TO_PARENT, 0.0f,
TranslateAnimation.RELATIVE_TO_PARENT, 0.86f
);
animation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
mhandle.post(new Runnable() {
#Override
public void run() {
setBallColors();
}
});
}
#Override
public void onAnimationRepeat(Animation animation) {}
#Override
public void onAnimationEnd(final Animation animation) {}
}
}
Here is my 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"
android:background="#FFFFFF"
tools:context="com.example.hp.colorspoof.MainActivity">
<!-- ball imageviews -->
<ImageView
android:id="#+id/ball1"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="left"
android:layout_marginLeft="40dp"
app:srcCompat="#drawable/ball_0" />
<ImageView
android:id="#+id/ball2"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center_horizontal"
app:srcCompat="#drawable/row2_2" />
<ImageView
android:id="#+id/ball3"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="right"
android:layout_marginRight="40dp"
app:srcCompat="#drawable/row3_1" />
</FrameLayout>
Below is a simple untested implementation of what you want to do. I unfortunately no longer have an environment for programming Android setup, so I can't test the code for you, but this should work.
Please note that I made use of negative margins because that is the easiest way to implement it, but it isn't necessarily the best way to achieve it. See here for more: Is it a bad practice to use negative margins in Android?
To provide a summary of the changes in the XML below from what you provided:
I provided a RelativeLayout to contain your playfield. It's generally a good practice to include a FrameLayout at the top level and then use a RelativeLayout or LinearLayout below it to contain the views that will need to be manipulated. RelativeLayout and LinearLayout provide good means of placing views in relation to each other. There is also a newer type of Layout called the ConstraintLayout that I'm not personally familiar with but you may want to look at instead of RelativeLayout. See more here: What are the differences between LinearLayout, RelativeLayout, and AbsoluteLayout?
I removed the android:layout_gravity statements. You don't need those with a RelativeLayout.
I utilized android:layout_alignParentTop and android:layout_marginTop to place the balls above the top of your layout by exactly the size of the ball.
I utilized android:layout_marginLeft, android:layout_centerHorizontal, and android:layout_marginRight to place the balls horizontally on the screen as you did.
XML below:
<?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"
android:background="#FFFFFF"
tools:context="com.example.hp.colorspoof.MainActivity">
<RelativeLayout
android:id="#+id/play_area"
android:layout_width="match_parent"
android:layout_height"match_parent">
<!-- ball imageviews -->
<ImageView
android:id="#+id/ball1"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentTop="true"
android:layout_marginTop="-30dp"
android:layout_marginLeft="40dp"
app:srcCompat="#drawable/ball_0" />
<ImageView
android:id="#+id/ball2"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="-30dp"
app:srcCompat="#drawable/row2_2" />
<ImageView
android:id="#+id/ball3"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_marginTop="-30dp"
android:layout_marginRight="40dp"
app:srcCompat="#drawable/row3_1" />
</RelativeLayout>
</FrameLayout>
I am developing an Android application where an activity displays content in a scrollview. At the top of the content there is a placeholder for an image to be displayed. The image is downloaded from the Internet and may take a few seconds until it is ready to be displayed. The image placeholder is initially empty. When the image is downloaded, it is dynamically added to the placeholder.
Initially I had the following problem.
The user starts the activity and scrolls down
The image starts to download in the background. When available, it is added to the placeholder
When the image is added to the placeholder, the contents of the scrollview change and the user experience is disrupted by the unwanted scrolling that occurs
To fix this, I added code to adjust the scroll position once the image view is added to the placeholder. The problem with this is that a flickering is caused on the scrollview during the display-image and adjust-scrollview process. The reason is that the scrollBy function is called from a runnable. Calling scrollBy outside the runnable does not cause flickering but the scroll position is incorrect - the reason for this is that there is not enough time for the items on the scroll view to recalculate/measure their dimensions/heights.
Here is a sample application the illustrates this problem:
public class MainActivity extends AppCompatActivity {
ScrollView scrollView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scrollView = findViewById(R.id.scrollview);
startImageDownload();
simulateImageScroll();
}
private void simulateImageScroll() {
// scroll to the bottom of the scroll view
scrollView.post(new Runnable() {
#Override
public void run() {
scrollView.scrollTo(0, scrollView.getMaxScrollAmount());
}
});
}
private void startImageDownload() {
Handler handler = new Handler(getMainLooper());
// simulate a delay for the image download to illustrate the flashing problem in the scrollview
handler.postDelayed(new Runnable() {
#Override
public void run() {
displayImage("");
}
}, 2000);
}
// when the image is downloaded we add it to the image container
private void displayImage(String imageFilename) {
// dynamically create an image and add it to the image container layout
RelativeLayout container = findViewById(R.id.imageContainer);
ImageView img = new ImageView(this);
// image should be loaded from the given filename - for now use a solid background and fixed height
img.setBackgroundColor(Color.BLUE);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT, 500);
container.addView(img, params);
adjustScrolling(container);
}
private void adjustScrolling(RelativeLayout container) {
// adjust scroll if the image is loaded before the current content
if (scrollView.getScrollY() > container.getTop()) {
container.measure(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
final int amountToScroll = container.getMeasuredHeight();
// the following does not cause flickering but scrolls to the wrong position
//scrollView.scrollBy(0, amountToScroll);
// adjust the scrollview so that it keeps the current view unchanged
scrollView.post(new Runnable() {
#Override
public void run() {
// this causes flickering but scrolls to the correct position
scrollView.scrollBy(0, amountToScroll);
}
});
}
}
}
And here is the layout file:
<ScrollView
android:id="#+id/scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:id="#+id/imageContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:background="#aa0000" >
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:background="#aa0000" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1"
android:textColor="#ffffff"
android:textSize="128dp"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:background="#aa0000" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2"
android:textColor="#ffffff"
android:textSize="128dp"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:background="#aa0000" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="3"
android:textColor="#ffffff"
android:textSize="128dp"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:background="#aa0000" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="4"
android:textColor="#ffffff"
android:textSize="128dp"/>
</RelativeLayout>
</LinearLayout>
</ScrollView>
Any ideas on how to fix this problem?
Edited:
Currently, your layout is flickering, because adding blue view cause redraw layout (and scroll). So scroll occurred once, and next you scrolled to the position you want. That's the second moving.
To solve this problem, you need to know how android draws view.
https://developer.android.com/guide/topics/ui/how-android-draws.html
Simply, onMeasure() - onLayout() - onDraw(). And you can add your layout code between onLayout() and onDraw(), by ViewTreeObserver().addOnGlobalLayoutListener().
https://developer.android.com/reference/android/view/ViewTreeObserver.OnGlobalLayoutListener.html
ps: I still recommend using nice and lovely image library, Picasso.
Fixed code is: Set scroll before draw() called. By this, you can draw only once.
public class MainActivity extends AppCompatActivity {
ScrollView scrollView;
int amountToScroll = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scrollView = findViewById(R.id.scrollview);
scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
scrollView.scrollBy(0, amountToScroll);
amountToScroll = 0;
}
});
startImageDownload();
simulateImageScroll();
}
private void simulateImageScroll() {
// scroll to the bottom of the scroll view
scrollView.post(new Runnable() {
#Override
public void run() {
scrollView.scrollTo(0, scrollView.getMaxScrollAmount());
}
});
}
private void startImageDownload() {
Handler handler = new Handler(getMainLooper());
// simulate a delay for the image download to illustrate the flashing problem in the scrollview
handler.postDelayed(new Runnable() {
#Override
public void run() {
displayImage("");
}
}, 2000);
}
// when the image is downloaded we add it to the image container
private void displayImage(String imageFilename) {
// dynamically create an image and add it to the image container layout
RelativeLayout container = findViewById(R.id.imageContainer);
ImageView img = new ImageView(this);
// image should be loaded from the given filename - for now use a solid background and fixed height
img.setBackgroundColor(Color.BLUE);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT, 500);
container.addView(img, params);
adjustScrolling(container);
}
private void adjustScrolling(RelativeLayout container) {
// adjust scroll if the image is loaded before the current content
if (scrollView.getScrollY() > container.getTop()) {
container.measure(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
amountToScroll = container.getMeasuredHeight();
}
}
}
I strongly recommend using Picasso. http://square.github.io/picasso/
This one line will fix all of your problem.
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
You can load your local image file or network image (url) into your imageView.
In your case, remove both startImageDownload() and simulateImageScroll(), and on onResume(), call displayImage().
Fixed displayImage():
private void displayImage(String imageFilename) {
// dynamically create an image and add it to the image container layout
RelativeLayout container = findViewById(R.id.imageContainer);
ImageView img = new ImageView(this);
// image should be loaded from the given filename - for now use a solid background and fixed height
img.setBackgroundColor(Color.BLUE);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT, 500);
container.addView(img, params);
Picasso.with(this).load(imageFilename).into(img);
adjustScrolling(container);
}
Or, if you want to solve this problem directly for academic reasons,
Do not adjust your scroll. It seems that it is not a real solution to use scrollBy to fix your problem. The real cause is the code that cause the UI to redraw. May be calling invalidate() or something like that.
Adding ImageView programmatically is not a good idea. Because your RecyclerView or ViewHolder of ListView cannot reuse the view, so it cause degrade performance. If you can avoid it, do that. (eg. use xml)
It seems that adding your ImageView to imageContainer is real problem. imageContainer has android:layout_height="wrap_content" property, and this means it has no fixed height, it depends on it's own child. Try to change to fixed value, for example: android:layout_height="500dp"
Well first if it's a single image on top then you don't have to create imageview dynamically just use it inside your XML file without Relative-layout. set to an default image. Use Image-View with adjustViewBounds="true" and scaleType="fitCenter" then you don't have to worry about the image scaling.
<ImageView
android:id="#id/img"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter" />
you can use Picasso http://square.github.io/picasso/ library as suggested by "Stanley Kou" for loading the image.
My Suggestion is to use Progress Bar, Start the Progress bar when image starts downloading and hide it once the image load is complete then let the user see the activity.
<ProgressBar
android:id="#+id/indeterminateBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
For more details, please check -
https://developer.android.com/reference/android/widget/ProgressBar.html
I have a problem with images. How can I bring an image in front of another one.
The problem is I create the images in code. So I can not change order in Layout.
You can use ImageView.bringToFront();, maybe is the best solution.
Here's the Tutorial
Let me know if you have any issue.
You can use RelativeLayout:
RelativeLayout rv = (RelativeLayout) findViewById(R.id.my_ph);
RelativeLayout.LayoutParams params;
ImageButton im1 = new ImageButton(this);
im1.setBackgroundResource(R.drawable.lamp);
im1.setId(i);
im1.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
TextView tx = (TextView) findViewById(R.id.textView1);
tx.setText("lamp #" + v.getId());
}
});
params = new RelativeLayout.LayoutParams(40, 40);
params.leftMargin = x;
params.topMargin = y;
rv.addView(im1, params);
XML Layout:
<RelativeLayout
android:id="#+id/my_ph"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="bottom">
<ImageView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="#drawable/map" />
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_below="#+id/image"
android:layout_alignParentLeft="true">
</TextView>
</RelativeLayout>
If you are creating images via code , you could use LayoutParams to give the second image a negative leftMargin.
RelativeLayout.LayoutParams imageParams = new RelativeLayout.LayoutParams
(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT);
imageParams.leftMargin = -20; // change this value
imageParams.addRule(RelativeLayout.RIGHT_OF,image1.getId());
image2.setLayoutParams(imageParams);
This would force the second image on top of the first image. By changing the left margin you could decide on how much you want the second image to move over the first.
I am trying to center a view within a parent RelativeLayout:
private void addLoadingAnimation() {
RelativeLayout mainView = (RelativeLayout) findViewById(R.id.medical_supply_tile_activity);
mainView.removeAllViews();
GifView gifView = new GifView(this);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
gifView.setId(R.id.loading_gif);
mainView.setBackgroundColor(getResources().getColor(android.R.color.background_light));
mainView.addView(gifView,layoutParams);
}
I have also tried adding layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 0); before the CENTER_IN_PARENT line. Nothing seems to be working. It is always aligned to the bottom right.
Here is my parent view:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/background_light"
tools:context=".MedecineTileActivity"
android:id="#id/medical_supply_tile_activity"
android:layout_gravity="left">
</RelativeLayout>
The gravity=left is because when the loading animation is removed, I insert fragments and want them to go to the left.
I have achieved this with TextViews and ImageViews by aligning the child View's right to the parent's right and also aligning the child View's left to the parent's left.
<TextView
style="#style/NewTextM2"
android:id="#+id/soft_dialog_info_item_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/<Parent>"
android:layout_alignLeft="#+id/<Parent>"
android:layout_alignRight="#+id/<Parent>"
android:gravity="center"
android:tag="item_text"
android:text="#string/text"
android:maxLines="1" />
This will align the view to the bottom center of the parent.
I've made the next layout xml code which I call it layout_one -
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:id="#+id/layout_one"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="50dp"
android:layout_marginTop="50dp"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="100dp"
android:text="Testing 1"
android:textSize="20sp" />
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/info_layout"
android:visibility="gone">
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
As you can see there are two layout in it - one with textview and button and one with textview.
The layout with the only textview - is gone, And i want by a click on the button, from the visible layout, it will be shown.
Now at the activity i wrote the next code -
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_layout);
ScrollView sv = new ScrollView(this);
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
sv.addView(ll);
LinearLayout newView0 = (LinearLayout)View.inflate(this, R.layout.layout_one, null);
LinearLayout newView1 = (LinearLayout)View.inflate(this, R.layout.layout_one, null);
LinearLayout newView2 = (LinearLayout)View.inflate(this, R.layout.layout_one, null);
LinearLayout newView3 = (LinearLayout)View.inflate(this, R.layout.layout_one, null);
ll.addView(newView0);
ll.addView(newView1);
ll.addView(newView2);
ll.addView(newView3);
setContentView(sv);
newView1.findViewById(R.id.layout_one).setBackgroundColor(0xff0000ff);
TextView tv3 = (TextView) newView3.findViewById(R.id.textView1);
tv3.setText("Suprise Suprise");
infoLay = (View) findViewById(R.id.info_layout);
ll.addView(newView3);
}
Now there is something I don't understad - How could I set an on click listener to the button that will know which layout to show?
Tanks for any kind of help
Actually, there are three linear layouts, which seems redundant.
You can set the onclick listener by checking if textview of each layout is empty or not.
First off, have a look at this http://developer.android.com/training/improving-layouts/reusing-layouts.html. Use that <include> tag instead of dynamically creating all these layouts in your Activity class. Define your ScrollView, and all your LinearLayouts in your test_layout.xml file.
Then, in your Activity, all you have to do is get a reference to those views that's you've defined using findViewById.
Once you've got that working we can address your question as follows:
setContentView(R.layout.test_layout);
LinearLayout layout1 = (LinearLayout)findViewById(R.id.layout1);
LinearLayout layout2 = (LinearLayout)findViewById(R.id.layout2);
LinearLayout layout3 = (LinearLayout)findViewById(R.id.layout3);
OnClickListener listener = new OnClickListener() {
#Override
public void onClick(View view) {
((View)view.getParent().getParent()).findViewById(R.id.textView2).setVisibility(View.VISIBLE);
}
});
layout1.findViewById(R.id.button1).setOnClickListener(listener);
layout2.findViewById(R.id.button1).setOnClickListener(listener);
layout3.findViewById(R.id.button1).setOnClickListener(listener);
I'd also add that it seems like you're trying to create a list here, in which case you should use a ListView instead of many LinearLayouts.