How to show long Strings in pages in android? - java

I have a large String from the database. I showed it in the TextView with scrolling.
This is a totally boring method to show large text though; I want to show data in pages.
There are multiple questions similar to this one, but I am not able to find any solutions from them; they are incomplete and off track.
Challenges
How to count number of lines that fit to screen?
How to split string in sub parts so that each substring fits to a page?

I think this should solve the problem,
1. it will split the large string
2. display on view as you want
So if u dont want to use Scroll View then well i tried something and i hope it helps
Following i done
1. inflate required views into parent view
2. set large text into Textview
3. Check if other text views are within the (visible) screen or not
4. update appropriately
Main Activity class
public class MainActivity extends Activity {
private TextView text1, text2;
private Context context;
private LinearLayout layout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = getLayoutInflater().getContext();
layout = (LinearLayout) findViewById(R.id.parentLayout);
setTextViews();
// checkViewAndUpdate();
layout.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
checkViewAndUpdate();
}
});
}
private void checkViewAndUpdate() {
Rect rect = new Rect();
layout.getHitRect(rect);
if (text1.getLocalVisibleRect(rect)) {
Toast.makeText(context, "visible", Toast.LENGTH_LONG).show();
} else {
// update if not visible decreasing the view text size
Toast.makeText(context, "Not visible", Toast.LENGTH_LONG).show();
}
if (text2.getLocalVisibleRect(rect)) {
Toast.makeText(context, "visible", Toast.LENGTH_LONG).show();
} else {
// update if not visible decreasing the view text size
Toast.makeText(context, "Not visible", Toast.LENGTH_LONG).show();
}
}
private void setTextViews() {
text1 = new TextView(context);
text2 = new TextView(context);
text1.setText("your link seems to work. where/when do u trying to call getXXXVisibleRect()? if u do it at onCreate your link seems to work. where/when do u trying to call getXXXVisibleRect()? if u do it at onCreate your link seems to work. where/when do u trying to call getXXXVisibleRect()? if u do it at onCreateyour link seems to work. where/when do u trying to call getXXXVisibleRect()? if u do it at onCreate ");
text2.setText("text2");
text1.setTextSize(30);
text2.setTextSize(30);
// layout.removeAllViews();
layout.addView(text1);
layout.addView(text2);
}
}

Related

Android Studio: Code in previous screen not continuing after calling "finish()" in activity

I'm new to Android Development and am trying to make a simple habit tracking app. The initial screen is a fragment called HabitFragment. It has a button that, when clicked, takes the user to an activity, called HabitDialogueActivity, where they create a new habit that they would like to keep track of. When the "done" button is pressed, I call the "finish()" method. In the app, this takes me back to the original screen. However, my code does not seem to continue as my log entries do not show up.
I have this onClickListener and some code after it, it is inside of my OnCreateView():
Button newHabitButton = view.findViewById(R.id.newHabitButton);
newHabitButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
goToDialogue();
}
});
if (HabitDialogueActivity.getHabitListSize() > habitListSize) {
Log.d("TAG", "adding to linearLayout, am in if statement");
habitListSize = HabitDialogueActivity.getHabitListSize();
Habit newHabit = HabitDialogueActivity.habitList.get(habitListSize - 1);
TextView text = new TextView(this.getContext());
text.setText(newHabit.habitName);
text.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
linearLayout.addView(text);
} else {
Log.d("TAG", "habit list size not changed");
}
and this is my goToDialogue():
private void goToDialogue() {
Log.d("TAG", "HabitFragment goToDialogue");
Intent intent = new Intent(HabitFragment.this.getActivity(), HabitDialogueActivity.class);
startActivity(intent);
}
My HabitDialogueActivity just has a few text fields, an ArrayList of habits, and a "done" button which calls finish(). It takes me back to my HabitFragment, but the Log entries in the if statement that follow the setOnClickListener do not show in the log. Why doesn't the code in HabitFragment continue to execute after I leave HabitDialogueActivity?
I am new to this website, so I'm sorry if I've left anything out.
Put your code inside onResume to rerun it when you go back to previously screen and remove it from on Create View. onResume will run after oncreate when you open the screen for the first time.
Check the docs
https://developer.android.com/guide/components/activities/activity-lifecycle
#Override
public void onResume() {
super.onResume();
// put your code here...
if (HabitDialogueActivity.getHabitListSize() > habitListSize) {
Log.d("TAG", "adding to linearLayout, am in if statement");
habitListSize = HabitDialogueActivity.getHabitListSize();
Habit newHabit = HabitDialogueActivity.habitList.get(habitListSize - 1);
TextView text = new TextView(this.getContext());
text.setText(newHabit.habitName);
text.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
linearLayout.addView(text);
} else {
Log.d("TAG", "habit list size not changed");
}
}
OnCreateView is only called when the Fragment is created. Since it wasn't destroyed when you navigated to the HabitDialogueActivity, OnCreateView isn't called again.
You can move your if statement inside the Fragment's onResume() method in order to check if new data is available each time you navigate back to the activity to which the Fragment is attached.
#Override
public void onResume() {
super.onResume();
if (HabitDialogueActivity.getHabitListSize() > habitListSize) {
Log.d("TAG", "adding to linearLayout, am in if statement");
habitListSize = HabitDialogueActivity.getHabitListSize();
Habit newHabit = HabitDialogueActivity.habitList.get(habitListSize - 1);
TextView text = new TextView(this.getContext());
text.setText(newHabit.habitName);
text.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
linearLayout.addView(text);
} else {
Log.d("TAG", "habit list size not changed");
}
}

Cannot use if statement in onSingleClick? Also need PDF loader on doubleclick

I have a horizontal scroll view, with several imageviews inside of it.
If I click once on the images, I want to show a toast. This toast has to be changed depending on a stringvariable that is set in a textview.
If there is a doubleclick on an image, I need to open a new activity that opens a PDF (embedded into the app).
At the moment I have:
public class activity_fruit extends AppCompatActivity {
TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle("Fruit");
setContentView(R.layout.activity_fruit);
textView = (TextView) findViewById(R.id.txtstatus);
textView.setText(((Globals) this.getApplication()).getTaal());
int fruit1 = R.drawable.kumato;
ImageView targetImageView1 = findViewById(R.id.img_fruit1);
targetImageView1.setOnClickListener(new DoubleClickListener() {
#Override
public void onSingleClick(View v) {
if(textView.equals("ENG")) {
Toast.makeText(getApplicationContext(), "eng single", Toast.LENGTH_SHORT).show();
}
if (textView.equals("")) {
Toast.makeText(getApplicationContext(), "nl single", Toast.LENGTH_SHORT).show();
}}
#Override
public void onDoubleClick(View v) {
Toast.makeText(getApplicationContext(), "double", Toast.LENGTH_SHORT).show();
}
});
Glide.with(this)
.load(fruit1)
.into(targetImageView1);
Everything loads just fine, but since adding the if statement to my onSingleClick(), the one tap doesn't work anymore. The double tap works just fine.
As said in the first few lines of this post, I also want to change my double tap code to open a new activity and then open a PDF (that is stored in the app itself) inside the app itself. So any help with that would also be appreciated.
Here:
textView.equals("ENG"))
You are comparing the text view object with a String. That will always return false!
Instead - retrieve the text from the textView - and compare that string with your other strings! As in:
textView.getText().equals("ENG")
You are like comparing a "box for eggs" with an egg. Instead, you first have to fetch an egg from that box, then you can compare that egg to your other egg.
instead of textView.equals("ENG")
Use this.
if(textView.getText().equals("ENG")) {
Toast.makeText(getApplicationContext(), "eng single", Toast.LENGTH_SHORT).show();
}
Try this
Use This
textView.getText().toString().trim().equals("ENG")
{
Toast.makeText(getApplicationContext(), "eng single", Toast.LENGTH_SHORT).show();
}
instead of
textView.equals("ENG")

How to dynamically add rows from a table (sqlite) to layout? (Android)

I am trying to take all the rows from my db and add it to the current layout, also, making each row clickable in the layout to take the user to a new screen with the id...
Here is my current code, but stuck on that part... I understand that I can put an onClickListener, but then does it have to be a button?
For a visual representation refer to a notepad app on any device where each note title appears and clicking on it takes you to that note.
public class MainActivity extends Activity implements OnClickListener {
private Button add_new_dictionary;
// Database helper
private DatabaseHelper db;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// db setup
db = new DatabaseHelper(getApplicationContext());
// get all dictionaries
List<db_dictionary> allDictionaries = db.getAllDictioniaries();
for (db_dictionary dictionary_found : allDictionaries) {
// create new view for each dictionary name include id and make it
// dynamic and include onclick to take to dictionary_view screen
Button dictionary_button = new Button(this);
}
add_new_dictionary = (Button) findViewById(R.id.add_new_dictionary);
}
#Override
public void onClick(View v) {
if (v == add_new_dictionary) {
Intent add_new_dictionary_intent = new Intent(MainActivity.this,
add_new_dictionary.class);
startActivity(add_new_dictionary_intent);
}
}
}
To re-iterate the question: How do I go about dynamically taking rows from my db and adding it to my layout dynamically based on how many results are returned from the query? (However, the rows should be able to point to a new screen with the dictionary id)
All views in android can implement the OnClickListener interface. So no, it doesn't HAVE to be a button.
As you've decided to use the activity to handle this then you need to tell your code to pass the event to your implementation wihin your activity.
// create new view for each dictionary name include id and make it
// dynamic and include onclick to take to dictionary_view screen
Button dictionary_button = new Button(this);
dictionary_button.setOnClickListener(this);
A trick I use to store information is the setTag method which would allow you to retrieve the correct reference during your onClick:
dictionary_button.setTag(some_record_id);
Then retrieve it later:
#Override
public void onClick(View v) {
if (v == add_new_dictionary) {
Intent add_new_dictionary_intent = new Intent(MainActivity.this,
add_new_dictionary.class);
startActivity(add_new_dictionary_intent);
}
else (
Object tag = v.getTag();
//now launch the detail activity using the data from the tag
}
}
You should really look into ListAdapters and cursors to do this properly, but this method should get you going for now
If you need to pick data from a db and show it as a list (getting click events) you should probably look into CursorAdapter and ListView
http://developer.android.com/reference/android/widget/CursorAdapter.html
http://developer.android.com/reference/android/widget/ListView.html
You can fins many examples on the web on how to use a cursoradapter and the listview

DialogFragment not visible but selectable

I have a very strange problem on Android using DialogFragments.
I have a FrameLayout with no content and the OnClickListener set to open a FragmentDialog where the user can choose what type of content he wants to add.
If I choose an image from the gallery, this image will be loaded and an image view inside the Frame-Layout is created and the image is shown. If the user clicks again on the layout the selection dialog should open again and the user can select a new image and the old one would be replaced.
This works quite well on my device with Android 4.1. But if I test it on Android 2.3 something strange happens:
The first dialog appears and the user can choose an image from the gallery. But if the user clicks again the dialog is not shown again. But the display becomes darker as if the dialog would be there but is not shown. If I click on the position where the selection dialog should be the gallery is started again. So the dialog is definitely there, but it is simply not shown.
I have tried almost everything that came to my mind(and what I found in the internet) to fix this issue, but it does not help anything. Of course I am using the support library to import the Fragment and DialogFragment.
I start this dialog from a Fragment which is embedded in a ViewPager. So it is basically a tabbed view. What's interesting: I I run into this bug and the display is just getting darker but no dialog is visible, I can cancel the invisible dialog and just drag the ViewPager a bit to left or right(to the next fragment) and if I get back and click on the content again the dialog is shown again.
But if I am dragging the ViewPager around there are no log messages so I have no idea why the dialog is suddenly visible again if I firstly move the page(only a bit is enough).
Here is some of my code:
in the onCreateView method I do the following:
rootView = inflater.inflate(args.getInt(ARG_OBJECT_TYPE), container, false);
editorActivity = ((NoteEditorActivity) EditorSectionFragment.this.getActivity());
// ...
if( fragmentId == R.layout.fragment_note_preferences_editor ){
// the other page
else if( fragmentId == R.layout.fragment_note_editor ) {
final View addLeftElement = rootView.findViewById( R.id.addLeftElement );
final View addRightElement = rootView.findViewById( R.id.addRightElement );
final View addTopElement = rootView.findViewById( R.id.addTopElement );
final View addBottomElement = rootView.findViewById( R.id.addBottomElement );
final FrameLayout contentLayout = (FrameLayout) rootView.findViewById( R.id.contentLayout );
showNavigation(editorActivity, contentLayout, editorActivity.currentPosition.x, editorActivity.currentPosition.y);
contentLayout.setOnClickListener( new OnClickListener() {
#Override
public void onClick(View v) {
Log.i("CONTENT CREATOR", "create new element at " + editorActivity.currentPosition);
//((NoteEditorActivity) EditorSectionFragment.this.getActivity()).showContentSelectionDialog();
((NoteEditorActivity) EditorSectionFragment.this.getActivity()).showCameraChooseDialog();
}
});
}
showCameraChoose(I also did it without the FragmentTransaction, but this didn't work either)
protected void showCameraChooseDialog() {
getSupportFragmentManager().executePendingTransactions();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
Fragment prev = getSupportFragmentManager().findFragmentByTag("cameraChoose");
if( prev != null ){
Log.i("PREVIOUS", "Remove previous dialog");
ft.remove(prev);
}
(new CameraSelectionDialog()).show( ft, "cameraChoose");
}
CameraSelectionDialog:
public static class CameraSelectionDialog extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final CharSequence[] items = {"Camera", "Gallery"};
AlertDialog.Builder builder = new AlertDialog.Builder( this.getActivity() );
builder.setTitle("Choose how to get the image!");
builder.setItems(items, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if( which == 0){
((NoteEditorActivity)(getActivity())).startCamera();
CameraSelectionDialog.this.dismiss();
}
else{
((NoteEditorActivity)(getActivity())).startGallery();
CameraSelectionDialog.this.dismiss();
}
}
});
return builder.create();
}
}
The startGallery method simply starts an gallery intent:
protected void startGallery() {
Intent pickPhoto = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(pickPhoto , ActionCodes.GALLERY_ACTION_CODE);
}
This image is handled in the onActivityResult method. But it does not matter what I choose to do in the onActivityResult method. Even if I don't create the image, the problem occurs.
I have no idea what I can do to solve this problem and I hope that maybe you can think of a reason for this strange bug. I am grateful for any advice or hint what could be wrong.
Thank you in advance!

How to implement a ProgressDialog correctly so that time-consuming methods are called in background?

I use an BaseAdapter to display a list of objects. This objects are fetched from a server. The getView() method of the BaseAdapter is the following:
/* (non-Javadoc)
* #see android.widget.Adapter#getView(int, android.view.View, android.view.ViewGroup)
*/
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout content = (LinearLayout) View.inflate(lexs, R.layout.favorite_item, null);
LinearLayout paragraphView = new LinearLayout(lexs);
paragraphView.setBackgroundColor(Color.RED);
paragraphView.setGravity(Gravity.CENTER_VERTICAL);
paragraphView.setOrientation(LinearLayout.HORIZONTAL);
ImageView img = new ImageView(lexs);
img.setImageResource(R.drawable.down);
paragraphView.addView(img);
img.setPadding(0, 0, 5, 0);
img.setOnClickListener(new WorkspaceOnClickListener(position));
TextView text = new TextView(lexs);
text.setTextColor(Color.WHITE);
text.setText(favorites.get(position).getParentChapter().getBook().getName() + ": §" + favorites.get(position).getName());
text.setOnClickListener(new ParagraphOnClickListener(position));
DisplayMetrics metrics = new DisplayMetrics();
lexs.getWindowManager().getDefaultDisplay().getMetrics(metrics);
int maxWidth = metrics.widthPixels - 100;
text.setMaxWidth(maxWidth);
text.setMinWidth(maxWidth);
paragraphView.addView(text);
ImageView imgClose = new ImageView(lexs);
imgClose.setMinimumHeight(30);
imgClose.setMinimumWidth(30);
imgClose.setImageResource(R.drawable.close);
imgClose.setPadding(5, 0, 0, 0);
paragraphView.addView(imgClose);
imgClose.setOnClickListener(new CloseListener(position));
content.addView(paragraphView);
content.setPadding(0, 0, 0, 10);
if (favorites.get(position).isExpanded()) {
LinearLayout textLayer = new LinearLayout(lexs);
textLayer.setBackgroundColor(Color.rgb(214, 214, 214));
LinearLayout left = new LinearLayout(lexs);
left.setOrientation(LinearLayout.VERTICAL);
ImageView moveUp = new ImageView(lexs);
moveUp.setImageResource(R.drawable.move_up);
moveUp.setOnClickListener(new MoveListener(UP, position));
moveUp.setPadding(0, 0, 0, 10);
left.addView(moveUp);
ImageView moveDown = new ImageView(lexs);
moveDown.setImageResource(R.drawable.move_down);
moveDown.setOnClickListener(new MoveListener(DOWN, position));
left.addView(moveDown);
TextView paragraphText = new TextView(lexs);
paragraphText.setText(favorites.get(position).getText());
paragraphText.setTextColor(Color.BLACK);
LinearLayout right = new LinearLayout(lexs);
right.setOrientation(LinearLayout.HORIZONTAL);
right.addView(paragraphText);
textLayer.addView(left);
textLayer.addView(right);
content.addView(textLayer);
img.setImageResource(R.drawable.up);
}
return content;
}
}
So I'd like that this whole method is called in background and during the method is executed, a ProgresDialog is shown. I defined the ProgressDialog the following way:
public class LoadingInformation {
private static ProgressDialog progressDialog;
public static void showProgressInformation(Context view) {
progressDialog = ProgressDialog.show(view, "Please wait...", "Doing Extreme Calculations...", true);
System.out.println("Start Loading Screen");
}
public static void stopShowingProgressInformation() {
Handler handler=new Handler();
handler.post(new Runnable(){public void run(){progressDialog.dismiss();}});
System.out.println("Stop Loading Screen");
}
}
But the problem is, i don't know how to implement the calls correctly. I tried to replace all lines:
adapter.notifyDataSetChanged();
With the following code:
public void updateFavoriteList() {
LoadingInformation.showProgressInformation(lexs);
new Thread() {
public void run() {
lexs.runOnUiThread(new Runnable() {
#Override
public void run() {
adapter.notifyDataSetChanged();
LoadingInformation.stopShowingProgressInformation();
}
});
}
}.start();
}
But unfortunately this doesn't work as expected. Has anybody a hint how to do it betteR?
The getView() method of the adapter isn’t responsible for downloading the content in the list, all it does is build the current row being displayed in the ListView. getView() doesn’t have anything to do with actually downloading the data from a network resource, which is where you wan’t the ProgressDialog.
When you instantiate the adapter (not shown in your code) you pass the data you want your BaseAdapter to populate the ListView with. Either the data has already been downloaded and simply handed off to the adapter, or the adapter itself does in the constructor.
If you wan’t the dataset for your ListView to change, you’re going to have to create some setter method or have a method in the adapter that refreshes the dataset from the network automatically. In any case though, this is where you want the ProgressDialog to show, not while the getView() method is setting up the ListView row.
P.S. One other suggestion I'd give is to make use of the convertView param passed to getView(). It'll improve the performance of your list by a lot if you have a large list. Check out Romain Guy's presentation about ListView in either the Google I/O 2009 or 2010 talks.
EDIT:
So “favorties” is an array (or List, etc.) of data for your ListView. You most likely pass the “favorites” data to the adapter via a constructor argument. At that point the data already exists in the adapter, or you’re passing a network location so the adapter can fetch the data and display it in the ListView.
For simplicity sake, lets say you download some string data into a String array, before passing it to the adapter. Each element contains a string to be displayed in your ListView via a TextView. You pass that array to the adapter and it handles formatting the ListView for you with the logic in the getView() method.
Now while you are downloading the data to populate the ListView with, you want to show the ProgressDialog to let the user know something is happening. Like some people have already said, you would use an AsyncTask to accomplish this. AsyncTask will allow you to display a ProgressDialog via onPreExecute() while you actually download the data in doInBackground() and get rid of the dialog in onPostExecute().
I hope that makes sense.
The time consuming tasks should be handled with an AsyncTask.
Read https://developer.android.com/resources/articles/painless-threading.html
It has been added to the Android framework to help you do these time consuming things and update progress dialogs without having to code the boilerplate of Tasks and Handlers yourself.

Categories