Android page control like iPhone page control - android

I would like to put something back to this VERY helpful site, so this is not really a question, but rather my solution to this issue. I would also add that this solution was gleaned form support from this site and many others, so it represents the combined efforts of many other developers. To them I say thank you!
The QUESTION is "How can you recreate the horizontal scrollView aspects of iPhone apps and the associated page control in the Android environment?"
This arose because I wanted to display the steps in recipe, the associated method fro each step and the necessary ingredients in a single scroll view. I also wanted a page control to display to the user where they were in the steps and allow them to move to any specific step
This part of my app displays the steps in a recipe. Each step appears on a page and has three components. A step identifier(ie. STEP 1, STEP 2), a method and a ingredients required for the step.
Below the recipe section we display a page control that show which page is active and can be used to navigate to specific pages. You will notice that the page control has image buttons and the two images are simple circles, one for the non selected page (page.png) and one for the selected page (page_selected.png)
When the activity is created the steps for the selected recipe are retrieved from the data and the scroller section created by adding a view for each step in the recipe. When you swipe the scroller the view snaps to the next or previous page and the pager display is updated to indicate which page you are on
First 3 xml layouts (res/layout)
recipe.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<!--Scroller section-->
<HorizontalScrollView
android:id="#+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="320dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginTop="100dp" >
<LinearLayout
android:id="#+id/methodScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
</LinearLayout>
</HorizontalScrollView>
<!-- pager section -->
<LinearLayout
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="430dp"
android:gravity="center"
android:orientation="horizontal" >
</LinearLayout>
</RelativeLayout>
recipesscroll.xml (the view that will be added to the scroller section for each recipe step. Note that the scroller section has a onTouchlistner in recipeViewController.java to handle page scrolling)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/recipeScroll"
android:layout_width="320dp"
android:layout_height="320dp"
android:gravity="center_vertical" >
<TextView
android:id="#+id/method"
style="#style/scrollMethod"
android:layout_width="wrap_content"
android:layout_height="200dp"
android:layout_alignParentTop="true"
android:text="Method" />
<TextView
android:id="#+id/ingredients"
style="#style/scrollIngredients"
android:layout_width="wrap_content"
android:layout_height="120dp"
android:layout_alignParentTop="true"
android:text="Ingredients" />
<TextView
android:id="#+id/methodStep"
style="#style/scrollStep"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_alignParentTop="true"
android:text="Step" />
</RelativeLayout>
recipiespager.xml ( the view that will be added to the pager section for each recipe step. Note that each of these will have a onClick event in recipeViewController.java that will scroll to the specific page selected in the pager control)
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
style="#style/pageButton"
android:layout_marginLeft="10dp"
android:layout_width="16dp"
android:layout_height="16dp"
android:onClick="selectPage">
</Button>
This is all brought together in recipeViewController.java
//my package name change this to yours
package com.infactdata.spinAdinner;
import java.util.ArrayList;
//DataModel is the model for my data change this to yours or ignore
because it is just away of holding the data that will populate the views
import com.infactdata.plist.DataModel;
import android.content.res.Resources;
import android.graphics.Typeface;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
public class RecipeViewController extends RootViewController {
private DataModel currentData;
HorizontalScrollView h_scroll;
int numberOfPages = 0;
int thePage;
int otherPage;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//first of the xml files
setContentView(R.layout.recipe);
//reference to my global variables
GlobalClass global = (GlobalClass)getApplicationContext();
//because I wanted a particular type face
Typeface face=Typeface.createFromAsset(getAssets(), "fonts/trebucit.ttf");
//VERY IMPORTANT because we need to use this to add the content to the scroll
and pager sections
LayoutInflater inflater = getLayoutInflater();
//current data held a dataModel
currentData = global.getCurrent();
currentName.setText(currentData.getName());
String imageFile = currentData.getImage();
Resources r = getResources();
int res = r.getIdentifier(imageFile, "drawable", "com.infactdata.spinAdinner");
image.setImageResource(res);
//recources that change the pager indicators to different images
thePage = r.getIdentifier("page_selected", "drawable","com.infactdata.spinAdinner");
otherPage = r.getIdentifier("page", "drawable", "com.infactdata.spinAdinner");
//Get the method(ArrayList) out of the currentData(DataModel). This is the array of
data that will fill the added view with different content (ie. the specific
instructions for the recipe step. This could be your own data array.
ArrayList<String[]> method = new ArrayList<String[]>();
method = currentData.getMethod(0);
numberOfPages = method.size();
//now to build the views by adding the content and then adding the text for that
content that reflects the instructions for the step in the recipe
for( int i = 0; i < method.size(); i++){
String[] methodStep = method.get(i);
//find the scroll view
LinearLayout scroll = (LinearLayout) findViewById(R.id.methodScrollView);
//find the recipe scroller. the second xml file
RelativeLayout step = (RelativeLayout)findViewById(R.id.recipeScroll);
//add the recipe step (step) to the scrollview (scroll)
step = (RelativeLayout)inflater.inflate(R.layout.recipescroll, scroll, false);
//add the instructions for this step in the recipe
TextView stage = (TextView)step.findViewById(R.id.methodStep);
stage.setText(methodStep[0].toString());
stage.setTypeface(face);
TextView methodText = (TextView)step.findViewById(R.id.method);
methodText.setText(methodStep[1].toString());
methodText.setTypeface(face);
TextView ingredients = (TextView)step.findViewById(R.id.ingredients);
ingredients.setText(methodStep[2].toString());
ingredients.setTypeface(face);
//create method step and add to scroll
scroll.addView(step);
//pager setup is a duplicate of the above
//find the pager
LinearLayout pager = (LinearLayout) findViewById(R.id.pager);
//find the pager button. the third xml file
Button page = (Button)inflater.inflate(R.layout.recipespager, pager, false);
//give each button it own ID. This will be used to test which button should be highlighted and used to move to a specific page. This is because the ID is equal to the page number (0 based of course)
page.setId(i);
//because this is a fresh construction we will be on page 0 so highlight that button
if (i == 0){
page.setBackgroundResource(thePage);
}
//create page control and add to pager
pager.addView(page);
}
//create the onTouch controls
h_scroll = (HorizontalScrollView) findViewById(R.id.scroll_view);
h_scroll.setOnTouchListener(scrolling);
}
private OnTouchListener scrolling = new OnTouchListener(){
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() ==
MotionEvent.ACTION_CANCEL ){
int scrollX = h_scroll.getScrollX();
int itemWidth = h_scroll.getMeasuredWidth();
int activePage = ((scrollX + itemWidth / 2) / itemWidth);
int scrollTo = activePage * itemWidth;
h_scroll.smoothScrollTo(scrollTo, 0);
//page control display the active page button
Log.v("MyDebug","Active page = "+activePage);
for(int i = 0; i < numberOfPages; i++){
Button aPage = (Button) findViewById(i);
if(i == activePage){
aPage.setBackgroundResource(thePage);
}else{
aPage.setBackgroundResource(otherPage);
}
}
return true;
} else {
return false;
}
}
};
//this is the onClick handler for the page buttons and moves the scroller to the page
associated with the button. That is through the button ID, which matches the page
number (0 based of course
public void selectPage(View v) {
int newPage = v.getId();
int itemWidth = h_scroll.getMeasuredWidth();
int scrollTo = newPage * itemWidth;
h_scroll.smoothScrollTo(scrollTo, 0);
//page control display
Log.v("MyDebug","Active page = "+newPage);
for(int i = 0; i < numberOfPages; i++){
Button aPage = (Button) findViewById(i);
if(i == newPage){
aPage.setBackgroundResource(thePage);
}else{
aPage.setBackgroundResource(otherPage);
}
}
}
public void finishActivity(View v){
//perform back action
finish();
}
public void nextActivity(View v){
//move to next activity
}
}
Well that was my solution. I am certain that there are much clever programers than me out there so I am sure someone can improve this. Anyhow THANKS stackoverflow!!!!

I think the GreenDroid library will help achieve something similar to the iPhone's UIPageControl.
Have a look at their app in marketplace GDCatalog. Also you can extract the files you want and make the pagecontrol. I've used it in my app and it works fine. Needs a bit optimisation to make it smoother.
https://github.com/cyrilmottier/GreenDroid

Related

Android - Cycling through Images component

I'm looking for a component like this:
If you have used Tinder, i want something like when you view a profile, how you can cycle through their pictures.
I'm pretty sure i can implement this manually, but was wondering if something already exists, and i don't really know how to look it up.
Thanks!
Edit: Also sorry for the bad title, didn't really know how to name these types of questions.
You can do your own implementation or could use some libraries. For you own implementation I would suggest using either ViewPager passing Views instead of fragments or PageTransformer if you want something more elaborate.
If you prefer libraries, I would recommend InfiniteCycleViewPager, sayyam's carouselview or you can go in a tour here: https://android-arsenal.com/tag/154, there is a lot of libraries with different implementations.
Example of implementation of an image slider using ViewPager:
First create your activity's xml with a ViewPager component:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager 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:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.stackoverflow.imageslider.MainActivity">
</android.support.v4.view.ViewPager>
Then in your activity's onCreate method instantiate the ViewPager and create an adapter for it:
ViewPager viewPager = findViewById(R.id.view_pager);
ViewPagerAdapter adapter = new ViewPagerAdapter(this, imageList);
viewPager.setAdapter(adapter);
In the ViewPagerAdapter class (that should extend PageAdapter), you will control the images overriding the method instantiateItem():
#NonNull
#Override
public Object instantiateItem(#NonNull ViewGroup container, int position) {
ImageView imageView = new ImageView(context);
imageView.setImageDrawable(imageList.get(position));
return imageView;
}
In this example imageList would be an List that is fulfilled somewhere else.
This example is based in a tutorial from codinginflow.com, and you can also take a look there.
Now let's see a simpler implementation, that would do just like you asked, touching the image sides instead of sliding.
Example of simpler implementation:
Create a layout with an ImageView and two buttons overriding it, one for next image on the right and one for previous image in the left:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:srcCompat="#tools:sample/backgrounds/scenic" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<Button
android:id="#+id/buttonPrevious"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#android:color/transparent" />
<Button
android:id="#+id/buttonNext"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#android:color/transparent" />
</LinearLayout>
</FrameLayout>
Then set the onClick of each button to get the images from a list and set in the ImageView.
final ImageView imageView = findViewById(R.id.imageView);
Button next = findViewById(R.id.buttonNext);
next.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
currentPosition ++;
imageView.setImageDrawable(drawableList.get(currentPosition));
}
});
Button previous = findViewById(R.id.buttonPrevious);
previous.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
currentPosition --;
imageView.setImageDrawable(drawableList.get(currentPosition));
}
});
drawableList would be a Drawable that is fulfilled somewhere else. You could also change to a different kind of image list, doesn't matter. current position would be and int that starts at 0.
For PageTransformer I would recommend Bincy Baby's answer and phantomraa's answer.
In case the link gets broken I'll leave Bincy Baby's code here:
viewPagerMusicCategory.setPageTransformer(false, new ViewPager.PageTransformer() {
#Override
public void transformPage(View page, float position) {
Log.e("pos",new Gson().toJson(position));
if (position < -1) {
page.setScaleY(0.7f);
page.setAlpha(1);
} else if (position <= 1) {
float scaleFactor = Math.max(0.7f, 1 - Math.abs(position - 0.14285715f));
page.setScaleX(scaleFactor);
Log.e("scale",new Gson().toJson(scaleFactor));
page.setScaleY(scaleFactor);
page.setAlpha(scaleFactor);
} else {
page.setScaleY(0.7f);
page.setAlpha(1);
}
}
}
);
I think you could also mix PageTransformer with the examples I gave.
The libraries each one already have a good documentation, if not in the android arsenal you can find it in GitHub, and even if I post some code here, if the library closes, gets outdated or something like that, the code will not be useful anymore.

How to create mini-drawer menu in Android?

I am looking to create a mini-drawer menu like in google example:
I have tried to create a layout that always stays there on ParentLeft, and the menu to overflow it when it opens, but it does not look natural. Does anyone know how do I do it?
Update
I have tried another way. To listen to menu sliding, and to catch when it is closed enough, then I can set menu size, and keep icons visible, but text to be gone.
#Override
public void onDrawerSlide(float v, int i) {
Log.d("onDrawerSlide", "v=" + v + " i=" + i);
if (i<previewsI && decreasingCount > 3) {
// check if menu is closed enough
if (i <100 && i > 50) {
// change menu size, and force menu to keep opened
mDrawer.setMenuSize(Utils.dpToPx(70, getApplicationContext()));
mDrawer.openMenu();
// TODO: hide menu items title, and let only icons to be visible
}
}
else if (i < previewsI)
// make sure the menu is closing
decreasingCount++;
previewsI = i;
}
It works, but not as smooth as I wish. Now I'd have to mess with smoothly opening it again.
Anyway, I don't think this is an elegant solution. I am sure there must be a better one out there.
I know this is a very old question, and i'm not sure if you are willing to use a library. But the MaterialDrawer library would offer a MiniDrawer implementation including the transformation to a normal drawer.
As shown in the screenshot the MiniDrawer also supports badges, and it also comes with an AccountSwitcher. Also with everything else.
The MiniDrawer uses the Crossfader library which allows the crossfade effect. The sample application of the Crossfader library also shows how to implement this with the MaterialDrawer
Here's the code which creates the shown sample (You can also find it over at the repository on GitHub):
DrawerBuilder builder = new DrawerBuilder()
.withActivity(this)
.withToolbar(toolbar)
.withInnerShadow(true)
.addDrawerItems(
//.. add some items ..
) // add the items we want to use with our Drawer
.withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
#Override
public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
//some actions inside the listener
return miniResult.onItemClick(drawerItem);
}
})
.withSavedInstance(savedInstanceState);
// build the main drawer
result = builder.buildView();
// build the miniDrawer
miniResult = new MiniDrawer().withDrawer(result).withInnerShadow(true).withAccountHeader(headerResult);
//define the width of the normal drawer, and the minidrawer
int first = (int) UIUtils.convertDpToPixel(300, this);
int second = (int) UIUtils.convertDpToPixel(72, this);
//create the Crossfader used to hook the MiniDrawer and the normal drawer together. This also handles the crossfade effect.
crossFader = new Crossfader()
.withContent(findViewById(R.id.crossfade_content))
.withFirst(result.getSlider(), first)
.withSecond(miniResult.build(this), second)
.withSavedInstance(savedInstanceState)
.build();
// inform the MiniDrawer about the crossfader.
miniResult.withCrossFader(new CrossfadeWrapper(crossFader));
I figured out a way to implement the mini navigation drawer using the SlidingPaneLayout.
Create a layout resource file and set SlidingPaneLayout as your parent view. SlidingPaneLayout requires two child views: a master view and a detail view. The master view will contain a list of all our menu options and the detail view will contain the content.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SlidingPaneLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--Master fragment-->
<fragment
android:name="com.ng.anthony.mininavigationdrawer.MasterFragment"
android:layout_width="220dp"
android:layout_height="match_parent"
android:id="#+id/fragment_master">
</fragment>
<!--Detail layout -->
<FrameLayout
android:layout_width="1000dp"
android:layout_height="match_parent"
android:layout_marginLeft="56dp">
</FrameLayout>
</android.support.v4.widget.SlidingPaneLayout>
Create a master fragment class. Inside your master fragment you should have a list view with all your menu options.
public class MasterFragment extends ListFragment {
public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_master, container);
setListAdapter(new MenuListAdapter(R.layout.row_menu_action_item, getActivity(), MenuActionItem.values()));
return view;
}
}
Add the master fragment layout to your layout resources folder
<?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">
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/darker_gray"
android:divider="#null">
</ListView>
</LinearLayout>
The master fragment contains a list view and uses an enumeration of menu options to populate the list.
public enum MenuActionItem {
ITEM1,
ITEM2,
ITEM3,
ITEM4,
ITEM5
}
The master fragment also contains a custom array adapter that displays the list of menu options. The custom array adapter inflates a row layout for each menu option.
import android.app.Activity;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
/**
* Created by Anthony on 16-01-25.
*/
public class MenuListAdapter extends ArrayAdapter<MenuActionItem> {
int resource;
Activity activity;
public MenuListAdapter(int resource, Activity activity, MenuActionItem[] items) {
super(activity, resource, items);
this.resource = resource;
this.activity = activity;
}
public View getView (int position, View convertView, ViewGroup parent) {
View rowView = convertView;
if(rowView == null) {
rowView = activity.getLayoutInflater().inflate(resource, null);
MenuItemViewHolder viewHolder = new MenuItemViewHolder();
viewHolder.menuItemImageView = (ImageView)rowView.findViewById(R.id.menu_item_image_view);
viewHolder.menuItemTextView = (TextView)rowView.findViewById(R.id.menu_item_text_view);
rowView.setTag(viewHolder);
}
MenuItemViewHolder holder = (MenuItemViewHolder)rowView.getTag();
if(position == MenuActionItem.ITEM1.ordinal()) {
holder.menuItemImageView.setImageDrawable(activity.getDrawable(R.drawable.ic_payment_white_24dp));
holder.menuItemTextView.setText(activity.getResources().getString(R.string.item1));
}
else if(position == MenuActionItem.ITEM2.ordinal()) {
holder.menuItemImageView.setImageDrawable(activity.getDrawable(R.drawable.ic_pets_white_24dp));
holder.menuItemTextView.setText(activity.getResources().getString(R.string.item2));
}
else if(position == MenuActionItem.ITEM3.ordinal()) {
holder.menuItemImageView.setImageDrawable(activity.getDrawable(R.drawable.ic_receipt_white_24dp));
holder.menuItemTextView.setText(activity.getResources().getString(R.string.item3));
}
else if(position == MenuActionItem.ITEM4.ordinal()) {
holder.menuItemImageView.setImageDrawable(activity.getDrawable(R.drawable.ic_shopping_cart_white_24dp));
holder.menuItemTextView.setText(activity.getResources().getString(R.string.item4));
}
else if(position == MenuActionItem.ITEM5.ordinal()) {
holder.menuItemImageView.setImageDrawable(activity.getDrawable(R.drawable.ic_work_white_24dp));
holder.menuItemTextView.setText(activity.getResources().getString(R.string.item5));
}
return rowView;
}
private static class MenuItemViewHolder {
public ImageView menuItemImageView;
public TextView menuItemTextView;
}
}
Add the row layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:gravity="center_vertical">
<ImageView
android:id="#+id/menu_item_image_view"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginRight="16dp"/>
<TextView
android:id="#+id/menu_item_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textColor="#android:color/white"/>
</LinearLayout>
In the end you should see something like this
You can download the sample project here: https://github.com/nganthony/MiniNavigationDrawer

Getting the value of clicked buttons and append them

I'm newbie in android development and going to create simple drag'n'Drop calculator.
My goal is to make buttons from 0 to 9 and create numbers by clicking them.
For example:
0 1 2 3 4 5 6 7 8 9
and by clicking them create number 245, then drag this number, for example, into the sum mark +, then repeat second number and automatically retrieve results.
First, I'll show my code now...
MainActivity.java
package com.coreprojects.calculator;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.app.Activity;
public class MainActivity extends Activity {
TextView calc_btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// This method comes from XML button = buttonClick
public void buttonClick(View v) {
// Textarea where numbers will be shown
TextView TV = (TextView) findViewById(R.id.calc_cache_1);
// Get the ID of buttons
Button calc_btn_1 = (Button) findViewById(R.id.button1);
Button calc_btn_2 = (Button) findViewById(R.id.button2);
// INT type numbers convert to string, because of [setText]
String buttonText_1 = calc_btn_1.getText().toString();
String buttonText_2 = calc_btn_2.getText().toString();
// Result as text
TV.setText(buttonText_1); // first number is not shown
TV.setText(buttonText_2); // second number
// alert
/**
String pressed = "Operation Done";
new AlertDialog.Builder(this).setTitle("result").setMessage(pressed)
.setNeutralButton("Done", null).show();
*/
}
}
activity_main.xml
<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"
tools:context=".MainActivity" >
<TextView
android:id="#+id/calc_cache_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="#string/main_text" />
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:clickable="true"
android:onClick="buttonClick"
android:text="#string/button_1" />
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="64dp"
android:clickable="true"
android:onClick="buttonClick"
android:text="#string/button_2" />
</RelativeLayout>
strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Calculator</string>
<string name="main_text"></string>
<string name="menu_settings">Settings</string>
<string name="button_1">1</string>
<string name="button_2">2</string>
</resources>
Now problem...
When i click on buttons, any time result shows number 2, because i think
TV.setText(buttonText_2) is second command and first one is not read any more.
I tried to write together, like TV.setText(buttonText_1 + buttonText_2), but now it results 12, even if i click any single button...
so how can I append numbers by clicking them? and also, if u see here, i have clickable button in XML, and get ID of pressed button, but i want it to be more dynamic.
For example: when i press button, don't get the ID of it, but simply identify the button ID and get value. i can show u simple analog in jQuery:
$(".button_class_not_ID").click(
var elementValue = $(this).html();
or
var elementValue = $(this).attr("id");
console.log(elementValue);
);

Adding imageView over another imageView cause resizing of the bottom one.How to prevent?

I have following problem:
in my layout xml I have relative layout in which is placed an ImageView(drawable from app /res folder, is drawn).
I need to add programmatically another ImageView(with another drawable from app resources) exactly on the same place as the initial one and to perform an animation on it.
I almost succeed ,a add new ImageView with new drawable and the layout params taken from the inital ImageView, and perform the animation on it,but the initial ImageView(which is bellow the newly added) is getting smaller - resize itself without reason(the other childs are OK).
How to prevent this?the both images are exactly the same width and height and I need to remain the same...
Thanks in advance.
P.S. update the question .
> <RelativeLayout> .... ... ... <ImageView deck1 > centerverticaly and
> leftof(other UI component) - this is the initial imageview and
> represents deck full of cards.... ... <ImageView deck2>
> centerverticaly and rightof(other UI component) - this is the second
> deck where the cards should be opened.... ... </RelativeLayout>
now I need to take a single card from deck1 and using animation to place it on deck2.
so I do the following:
if(animatingView==null){
ImageView animatingview = new ImageView(this.context);
animatingView.setImageBitmap(R.drawable.backofthecard);
animatinView.setLayoutParams(deck1.getLayoutParams);
RelativeLayout.add(animatingView);
}else{
animatingView.setVisible(visible);
}
animatingView.startAnimation(deckTranslateAnimation);
.
.
..
OnAnimationEnd{animatingView.setVisible(invisible)}
all of the drawables are equal(width and height),so I expect that there won't be any problems ,but when the animatingView is added to a Layout - deck1 get smaller,resize itself,it is still clickable and displayed but is smaller(and because it gets smaller all the other childs that depend on it,change their places...)
Sorry I didn't use the real code and xml,but right now I am not in front of them...
Edit:Solved.Here is the code:
if(animatingView==null){
animatingView = new ImageView(context);
animatingView.setImageResource(R.drawable.back);
RelativeLayout.LayoutParams params = new LayoutParams(animatingView.getDrawable().getMinimumWidth(), animatingView.getDrawable().getMinimumHeight());
params.addRule(RelativeLayout.ALIGN_LEFT, this.getDeckView().getCardView().getId());
params.addRule(RelativeLayout.ALIGN_TOP, this.getDeckView().getCardView().getId());
animatingView.setLayoutParams(params);
Can you show the code you are using?
Anyway, i think it is better to use FrameLayout to show views that may overlapped to each other. My first thought without seeing the code is to wrap the existing ImageView with FrameLayout. Then when you want to programmatically add new ImageView, you can do it by adding it as FrameLayout's child. FrameLayout renders view in different layer, so the old one should not be affected when you do something with the newly added view.
[updated]
I just tried to implement placing imageview over another imageview. Anyway, I don't seem to get the problem on the size of the overlapped image. Here are my implementation. Please try this and see if it worked or not. You may have to change some variables though.
.java
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
public class ImageStackActivity extends Activity {
Context context;
RelativeLayout relativeLayout;
ImageView deck1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
context = this.getApplicationContext();
deck1 = (ImageView)findViewById(R.id.deck1);
Button button = (Button)findViewById(R.id.button);
Button button2 = (Button)findViewById(R.id.button2);
relativeLayout = (RelativeLayout)findViewById(R.id.relative_layout);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ImageView img = new ImageView(context);
img.setBackgroundResource(R.drawable.photo3);
img.setLayoutParams(deck1.getLayoutParams());
relativeLayout.addView(img);
Animation anim = AnimationUtils.loadAnimation(context, android.R.anim.fade_in);
img.startAnimation(anim);
}
});
button2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(relativeLayout.getChildCount()>2){
relativeLayout.removeViewAt(2);
}
}
});
}
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/relative_layout"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/deck1"
android:src="#drawable/photo2"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/deck2"
android:src="#drawable/photo3"
android:layout_toRightOf="#id/deck1"
/>
</RelativeLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/button"
android:text="add image"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/button2"
android:text="clear"
/>
</LinearLayout>
I had the same problem and I solved it with Scaling the other picture, mby this will help you, tell me if you find any good in this code :)
public Bitmap decodeFile(String path, Integer size){
File f = new File(path);
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//The new size we want to scale to
if(size == 0)
size = 70;
//Find the correct scale value. It should be the power of 2.
int scale=1;
while(o.outWidth/scale/2>=size && o.outHeight/scale/2>=size)
scale*=2;
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}

How to layout Array of buttons to fit in any screen size

I have created an array of buttons for my app. Now I am not able to manage the layout of these array of buttons. As a result of this, whenever I add image or change width of the buttons it's going out of the horizontal screen of the device. So is there any way to manage these Array of buttons so that they can fit in any screen size.
Here is my code:
XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:id="#+id/liVLayout"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</LinearLayout>
<LinearLayout
android:id="#+id/liVLayout1"
android:orientation="vertical"
android:layout_below="#+id/liVLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView android:text="All Contacts"
android:id="#+id/textView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#android:color/black"
android:background="#808080">
</TextView>
</LinearLayout>
</RelativeLayout>
Java:
public class CalenderForm extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
createCalender();
}
public void createCalender()
{
RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams
(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
);
LinearLayout layoutVertical = (LinearLayout) findViewById(R.id.liVLayout);
LinearLayout rowLayout=null;
Button[][] buttons = new Button[6][7];
int count=43;
for (int i = 0; i<6; i++)
{
if(count%7==1)
{
rowLayout = new LinearLayout(this);
layoutVertical.addView(rowLayout,p);
count=count-7;
}
for(int j=0;j<7;j++)
{
buttons[i][j]=new Button(this);
buttons[i][j].setBackgroundResource(R.drawable.icon);
rowLayout.addView(buttons[i][j], p);
}
}
}
}
Snapshot before inserting image:
Snapshot before inserting image:
I know this doesn't directly answer your question, but I just want to help you out. If you're building a calendar app, creating lots of buttons really isn't the way to go:
You will have problems on different ROMs because of skins, etc.
You will not have full control over the layout (again because of the skins)
You will run into spacing issues
You will allocate a lot of memory (lots of Button objects, etc.) which will cause your app to be slow.
What I recommend is implementing your own custom View. I recently worked on a calendar app myself and tried using a GridView for the month, and that really didn't work out well (although it looked like it would), so I ultimately created my own View, which worked out perfect.
What I found very useful was Android's default, open source Calendar app. You'll find source code in there for both a month view and a day / week view (with an hour scale, etc.).
You could try a TableLayout and set the columns wrappable:
Found a nice tutorial with examples -> Android TableLayout Tutorial
To make a column wrappable (to reduce it’s width and wrap it’s content if other columns in the table are taking too much space and pushing some columns off the screen), use setColumnShrinkable to mark it shrinkable.
sounds promising
just replace this code.use weightsum property of linear and layout_weight of buttons.
package com.android.manager;
import android.app.Activity;
import android.os.Bundle;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.LinearLayout;
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
createCalender();
}
public void createCalender()
{
LinearLayout layoutVertical = (LinearLayout) findViewById(R.id.liVLayout);
LinearLayout rowLayout=null;
Button[][] buttons = new Button[6][7];
int count=43;
**LayoutParams param = new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT,1);**
for (int i = 0; i<6; i++)
{
if(count%7==1)
{
rowLayout = new LinearLayout(this);
**rowLayout.setWeightSum(7);**
**layoutVertical.addView(rowLayout,param);**
count=count-7;
}
for(int j=0;j<7;j++)
{
buttons[i][j]=new Button(this);
buttons[i][j].setBackgroundResource(R.drawable.icon);
**rowLayout.addView(buttons[i][j],param);**
}
}
}
}

Categories

Resources