Scroll TextView to text position - java

I want to scroll my TextView to make visible a specific position in the text. How can I do that? I tried bringPointIntoView (int offset) but without success.
Source code:
public class TextScrollActivity extends Activity {
public void onCreate (final Bundle savedInstanceState) {
super.onCreate (savedInstanceState);
final int position = 500;
final TextView textView = new TextView (this);
final ScrollView scrollView = new ScrollView (this);
scrollView.addView (textView);
Button button = new Button (this);
button.setText ("Scroll to " + position);
LinearLayout layout = new LinearLayout (this);
layout.setOrientation (LinearLayout.VERTICAL);
layout.addView (scrollView,
new LayoutParams (LayoutParams.FILL_PARENT, 200));
layout.addView (button, new LayoutParams (LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
StringBuilder builder = new StringBuilder ();
for (int i = 0; i < 1000; i++)
builder.append (String.format ("[ %05d ] ", i));
textView.setText (builder);
setContentView (layout);
button.setOnClickListener (new OnClickListener () {
public void onClick (View v) {
System.out.println (textView.bringPointIntoView (position * 10));
// scrollView.scrollTo (0, position * 10); // no
}
});
}
}

For those who have the same problem, I finally made my own implementation of bringPointIntoView:
public static void bringPointIntoView (TextView textView,
ScrollView scrollView, int offset)
{
int line = textView.getLayout ().getLineForOffset (offset);
int y = (int) ((line + 0.5) * textView.getLineHeight ());
scrollView.smoothScrollTo (0, y - scrollView.getHeight () / 2);
}
Don't hesitate if you have a better solution.

Does adding a movement method to the text view solve the problem?
textView.setMovementMethod(new ScrollingMovementMethod());

Just FYI for anyone else with the same problem, on a listView with large listItems, the overloaded bringPointIntoView can be passed a ListView instead of a ScrollView and use the ScrollTo method instead of smoothScrollTo.

Related

Getting a view's index in a LinearLayout

So I have a LinearLayout set up in my XML file, and I dynamically add a bunch of CardViews to it through code upon startup of my activity. How can I make it so that when I click on any of the CardViews, I am able to obtain its position?
I tried setting up on an onClickListener for the LinearLayout, as well as an OnClickLIstener for each individual card, but couldn't find a way to obtain the index of the card that was clicked.
I'd really like to know where to put the onClickListener, and how to obtain the position that was clicked so that I can start a new activity based on what was clicked.
Here is my code:
private LinearLayout sLinearLayout;
private CardView[] cardViews;
private Workout[] workouts;
private ViewGroup.LayoutParams params;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.saved_workouts);
Intent intent = getIntent();
Parcelable[] parcelableArrayExtra = intent.getParcelableArrayExtra(MainActivity.EXTRA_WORKOUTS);
workouts = new Workout[parcelableArrayExtra.length];
System.arraycopy(parcelableArrayExtra, 0, workouts, 0, parcelableArrayExtra.length);
sLinearLayout = findViewById(R.id.viewList);
// Set the CardView layoutParams
params = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
);
populateCardViews();
populateLayout();
}
//TODO: this method will populate the linear layout, filling the list.
private void populateLayout() {
for (CardView cardView : cardViews) {
sLinearLayout.addView(cardView);
}
}
//TODO: this method will fill up the CardViews array with an array of workouts.
private void populateCardViews() {
cardViews = new CardView[workouts.length];
for(int i = 0; i < workouts.length; i++) {
CardView card = new CardView(this);
card.setClickable(true);
card.setLayoutParams(params);
// Set CardView corner radius
card.setRadius(9);
// Set cardView content padding
card.setContentPadding(15, 15, 15, 15);
// Set a background color for CardView
card.setCardBackgroundColor(Color.BLUE);
// Set the CardView maximum elevation
card.setMaxCardElevation(50);
// Set CardView elevation
card.setCardElevation(25);
// Initialize a new TextView to put in CardView
TextView tv = new TextView(this);
tv.setLayoutParams(params);
tv.setText("Workout WorkTime: " + workouts[i].getWorkTime());
tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 30);
tv.setTextColor(Color.WHITE);
card.setTag(workouts[i].getWorkTime());
card.addView(tv);
cardViews[i] = card;
}
}
I think you can setOnClickListener for each individual card. The index of clicked card is i
for (int i = 0; i < workouts.length; i++) {
...
final int finalI = i;
card.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i("TAG", "You click at card: " + finalI);
}
});
}
I not good to add so much layout programmatically. You can use a recycler view and an adapter to show a list of items. You can read this: https://developer.android.com/guide/topics/ui/layout/recyclerview
By the way, in your case: when you create a Cardview, just add onClickListener to it and the index of your Cardview is the index of it in Cardview list.
CardView cardView = new CardView(this);
cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//handle click here
}
});
See if this works.
cardview.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
int index = linearLayout.indexOfChild(v);
}
});

Android How to change data of Textview by clicking on button

First of all, the app looks like this.
How to make - if I click on Add, on its column the textview is updated with value + 1?
I'm creating TextView and Button in a Loop;
for(int i = 0;i < playercountint; i++)
{
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,(100/playercountint)));
layout.setGravity(Gravity.CENTER_HORIZONTAL);
TextView tt = new TextView(this);
tt.setText("0");
tt.setTextSize(14);
tt.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
tt.setGravity(Gravity.CENTER_HORIZONTAL);
Button btadd = new Button(this);
btadd.setText("Add");
btadd.setId(2);
btadd.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
????? what here?
}
});
}
What should be written in onClick function , so only TextView value which is in buttons column is changed.
There is one outer LinearLayout which is horizontally oriented, and those which are created within a loop is vertical Linear Layouts.
Maybe i should create a template for 1 loop iteration?
First make your textview final and them set it's value in onClick
for(int i = 0;i < playercountint; i++)
{
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,(100/playercountint)));
layout.setGravity(Gravity.CENTER_HORIZONTAL);
final TextView tt = new TextView(this);
tt.setText("0");
tt.setTextSize(14);
tt.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
tt.setGravity(Gravity.CENTER_HORIZONTAL);
Button btadd = new Button(this);
btadd.setText("Add");
btadd.setId(2);
btadd.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
tt.setText(String.valueOf(Integer.parseInt(tt.getText())+1));
}
});
}
You can write one function that returns linearlayout:
public View getPlayerView(){
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,(100/playercountint)));
layout.setGravity(Gravity.CENTER_HORIZONTAL);
final TextView tt = new TextView(this);
tt.setText("0");
tt.setTextSize(14);
tt.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
tt.setGravity(Gravity.CENTER_HORIZONTAL);
Button btadd = new Button(this);
btadd.setText("Add");
btadd.setId(2);
btadd.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
tt.setText(String.valueOf(Integer.parseInt(tt.getText())+1));
}
});
layout.add(tt);
layout.add(btadd);
return layout;
}
Call this function in a loop.
tt.setText("something");
tt.invalidate();
my bad I didn't even notice it was a for loop uh you need to hold a reference to the text view.. make your textview final
tt.setText(Integer.parse(tt.getText().toString()) + 1);
But, I strongly recommend you design UI (layout) in the *.xml file!
See more: http://developer.android.com/guide/topics/ui/declaring-layout.html
You should provide your TextView with an unique id (.setId(...)). Having this, in your onClick method simply use something like this:
final TextView tv = (TextView) findViewById(R.id.your_textview_id);
final String cur_text = tv.getText();
Integer plus_one = Integer.valueOf(cur_text);
plus_one++;
tv.setText(plus_one.toString());
Didn't try it but should work.
static int counter = 0;
btn_Add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
counter ++;
tv_Display.setText("Your Total is : " + counter);
}
});

Arrange buttons from bottom instead of top?

I am dynamically creating the buttons. But the problem is they are getting created from top. I want to create it from bottom .
public class MainActivity extends Activity implements View.OnClickListener {
int i, j, butNum, lay1num = 1, lay2num = 100, lay3num = 100, store;
Button[] Button;
EditText numBut;
LinearLayout mainLayout;
LinearLayout[] subLayout;
LinearLayout.LayoutParams params;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
butNum = 5;
Button = new Button[butNum];
subLayout = new LinearLayout[3];
LinearLayout mainLayout = new LinearLayout(this);
mainLayout.setOrientation(LinearLayout.HORIZONTAL);
mainLayout.setWeightSum(90);
mainLayout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
layoutGen();
for (j = 0; j < butNum; j++) {
int value = j + 1;
Button[j] = new Button(this);
Button[j].setText("" + value);
Button[j].setLayoutParams(new LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
Button[j].setTextSize(20);
Button[j].setTag(value);
Button[j].setId(j);
subLayout[0].addView(Button[j]);
Button[j].setOnClickListener(this);
}
mainLayout.addView(subLayout[0], params);
setContentView(mainLayout);
}
Is there anyway I can create buttons which are aligned to the bottom.
subLayout.setGravity(Gravity.BOTTOM);
You nay need to set size of layout to match_parent.
Eventually You may set a layout_gravity like here

Question about arrays and buttons in eclipse + android java project

well im kind of new to eclipse anyways i was wondering is there a way for me to create an array of buttons in the java code rather then a xml file, then define there positions on the layout.
Every Button object is a view itself. Therefore, it can be added to a parent Layout (like the LinearLayout). The easiest way IMHO is creating the XML only for the things you know that will not change, or maybe using a TableLayout. Then, add the buttons.
LinearLayout mainLayout = findViewById(R.id.mainLayout);
Button[] btnArray = new Button[3];
for(Button button : btnArray){
button = new Button(/*Required params */);
// button.something , play with text and onclick and positions...
mainLayout.addView(button);
}
Is this what you're trying to do?
LinearLayout linear = (LinearLayout) findViewById(R.id.linear);
for (int i = 1; i <= 20; i++) {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
btn = new Button(this);
btn.setId(i);
final int id_ = btn.getId();
btn.setText("button " + id_);
btn.setBackgroundColor(Color.rgb(70, 80, 90));
linear.addView(btn, params);
btn1 = ((Button) findViewById(id_));
btn1.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Toast.makeText(view.getContext(),
"Button clicked index = " + id_, Toast.LENGTH_SHORT)
.show();
}
});
}

Create a new TextView programmatically then display it below another TextView

String[] textArray={"one","two","asdasasdf asdf dsdaa"};
int length=textArray.length;
RelativeLayout layout = new RelativeLayout(this);
RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
for(int i=0;i<length;i++){
TextView tv=new TextView(getApplicationContext());
tv.setText(textArray[i]);
relativeParams.addRule(RelativeLayout.BELOW, tv.getId());
layout.addView(tv, relativeParams);
}
I need to do something like that.. so it would display as
one
two
asdfasdfsomething
on the screen..
If it's not important to use a RelativeLayout, you could use a LinearLayout, and do this:
LinearLayout linearLayout = new LinearLayout(this);
linearLayout.setOrientation(LinearLayout.VERTICAL);
Doing this allows you to avoid the addRule method you've tried. You can simply use addView() to add new TextViews.
Complete code:
String[] textArray = {"One", "Two", "Three", "Four"};
LinearLayout linearLayout = new LinearLayout(this);
setContentView(linearLayout);
linearLayout.setOrientation(LinearLayout.VERTICAL);
for( int i = 0; i < textArray.length; i++ )
{
TextView textView = new TextView(this);
textView.setText(textArray[i]);
linearLayout.addView(textView);
}
Try this code:
final String[] str = {"one","two","three","asdfgf"};
final RelativeLayout rl = (RelativeLayout) findViewById(R.id.rl);
final TextView[] tv = new TextView[10];
for (int i=0; i<str.length; i++)
{
tv[i] = new TextView(this);
RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams
((int)LayoutParams.WRAP_CONTENT,(int)LayoutParams.WRAP_CONTENT);
params.leftMargin = 50;
params.topMargin = i*50;
tv[i].setText(str[i]);
tv[i].setTextSize((float) 20);
tv[i].setPadding(20, 50, 20, 50);
tv[i].setLayoutParams(params);
rl.addView(tv[i]);
}
public View recentView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Create a relative layout and add a button
relativeLayout = new RelativeLayout(this);
btn = new Button(this);
btn.setId((int)System.currentTimeMillis());
recentView = btn;
btn.setText("Click me");
relativeLayout.addView(btn);
setContentView(relativeLayout);
btn.setOnClickListener(new View.OnClickListener() {
#Overr ide
public void onClick(View view) {
//Create a textView, set a random ID and position it below the most recently added view
textView = new TextView(ActivityName.this);
textView.setId((int)System.currentTimeMillis());
layoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
layoutParams.addRule(RelativeLayout.BELOW, recentView.getId());
textView.setText("Time: "+System.currentTimeMillis());
relativeLayout.addView(textView, layoutParams);
recentView = textView;
}
});
}
This can be modified to display each element of a String array in different TextViews.
You're not assigning any id to the text view, but you're using tv.getId() to pass it to the addRule method as a parameter. Try to set a unique id via tv.setId(int).
You could also use the LinearLayout with vertical orientation, that might be easier actually. I prefer LinearLayout over RelativeLayouts if not necessary otherwise.

Categories

Resources