OnScrollChangeListener for ScrollView - android-studio

I would like to make a function to intercept a certain scroll at the top of the view.
to do this I'm trying to use OnScrollChangeListener.
My view contains a ScrollView
<ScrollView 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/scrollViewClientPhysique"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/fond"
tools:context=".client.FicheClient">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">**strong text**
and I initialize addOnScrollChangedListener in a function I call inside onCreateView
fun initializeInfiniteScroll(){
val scrollView = myView.findViewById<View>(R.id.scrollViewClientPhysique) as ScrollView
scrollView.viewTreeObserver.addOnScrollChangedListener {
if (scrollView != null) {
val view = scrollView.getChildAt(scrollView.childCount - 1)
val diff =
view.bottom + scrollView.paddingBottom - (scrollView.height + scrollView.scrollY)
if (diff == 0) {
// do stuff
}
}
}
}
but when when I scroll the view I don't enter addOnScrollChangedListener to intercept how many dp the scroll is.
what am I doing wrong?

Please update your ScrollChangedListener as mentioned below.
public class MainActivity extends AppCompatActivity implements View.OnTouchListener,
ViewTreeObserver.OnScrollChangedListener {
ScrollView scrollView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scrollView = findViewById(R.id.scrollView);
scrollView.setOnTouchListener(this);
scrollView.getViewTreeObserver().addOnScrollChangedListener(this);
}
public void onScrollChanged(){
View view = scrollView.getChildAt(scrollView.getChildCount() - 1);
int topDetector = scrollView.getScrollY();
int bottomDetector = view.getBottom() - (scrollView.getHeight() + scrollView.getScrollY());
//TODO: Just added for testing/understanding. Please add/replace your own logic..
if(bottomDetector == 0 ){
Toast.makeText(this,"Scroll View bottom reached",Toast.LENGTH_SHORT).show();
}
if(topDetector <= 0){
Toast.makeText(this,"Scroll View top reached",Toast.LENGTH_SHORT).show();
}
}
#Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
}

Related

ExoPlayer2 Zoomable View?

There are what appear to be several clones of the same answer for the first version of Exoplayer and the original Android media player, but they do not compile on Exoplayer2, which reorganized quite a bit of the internal code.
A reasonably-diligent search has not found anything in the way of a library or example code to do this (e.g. pinch zoom and scroll, etc.) There's plenty of code around to do it for still images (e.g. retrieved through Picasso, etc)
Does anyone have a sample that will build and work with ExoPlayer2?
Thanks in advance!
Update: The problem appears to be that I cannot either subclass or attach a VideoListener to a SimpleExoPlayer instance; attempting to do so leaves you with nothing, as the instance has already attached its own listener which pays exactly zero attention to aspect ratio when a TextureView is involved. This makes the video completely unusable; a listener could correct that quite easily, but there appears to be no way to attach it (the methods to do so are marked deprecated, and if you try to use them anyway you get no video output.)
This code will paint and run the ua.pohohalo.zoomabletextureview (or just a plain TextureView) but I cannot attach a videolistener to it and the default, when it initializes, fits the video to the view size vertically in portrait mode which destroys the aspect ratio. It also has serious glitches if you resize the video below the display window size but I can test for and fix that in polohalo's code. What I've not figured out how to do is to get the original display to honor the original aspect ratio or to attach a VideoListener to set it on init -- it works fine if I use a PlayerView, but that's not able to be extended to support translations. The "VideoListener" prototype in this codeblock should fix the aspect ratio problem -- that's what I've been unable to attach or find a way to set a flag on the original view (which would also do the job) that tells ExoPlayer to honor the original aspect ratio and fit within the screen size.
The call to simpleExoPlayerView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIT), which works on a PlayerView, is not valid on a TextureView -- it appears that the mode defaults to RESIZE_MODE_FILL and I cannot find a method to set it to FIT.
package net.cudasystems.android.videotest;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.TextureView;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.DefaultRenderersFactory;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.VideoListener;
public class MainActivity extends AppCompatActivity {
private String mURL = "http://point-at-an-mp4-file";
TextureView mPlayerView;
SimpleExoPlayer player = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPlayerView = findViewById(R.id.video_view2);
}
private void initializePlayer() {
DefaultRenderersFactory renderersFactory =
new DefaultRenderersFactory(this, DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON);
VideoListener mVideoListener = new VideoListener() {
#Override
public void onRenderedFirstFrame() {
}
#Override
public void onVideoSizeChanged(int width, int height, int rotation, float pixelWidthHeightRatio ) {
String TAG = "VideoSizeChange";
int viewWidth = mPlayerView.getWidth();
int viewHeight = mPlayerView.getHeight();
double aspectRatio = (double) height / width;
int newWidth, newHeight;
if (viewHeight > (int) (viewWidth * aspectRatio)) {
// limited by narrow width; restrict height
newWidth = viewWidth;
newHeight = (int) (viewWidth * aspectRatio);
} else {
// limited by short height; restrict width
newWidth = (int) (viewHeight / aspectRatio);
newHeight = viewHeight;
}
int xoff = (viewWidth - newWidth) / 2;
int yoff = (viewHeight - newHeight) / 2;
Log.v(TAG, "video=" + width + "x" + height +
" view=" + viewWidth + "x" + viewHeight +
" newView=" + newWidth + "x" + newHeight +
" off=" + xoff + "," + yoff);
Matrix txform = new Matrix();
mPlayerView.getTransform(txform);
txform.setScale((float) newWidth / viewWidth, (float) newHeight / viewHeight);
txform.postTranslate(xoff, yoff);
mPlayerView.setTransform(txform);
}
};
player = ExoPlayerFactory.newSimpleInstance(
renderersFactory,
new DefaultTrackSelector(), new DefaultLoadControl());
player.setVideoTextureView(mPlayerView);
// mPlayerView.setPlayer(player);
player.setPlayWhenReady(true);
Uri uri = Uri.parse(mURL);
MediaSource mediaSource = buildMediaSource(uri);
player.prepare(mediaSource, true, true);
}
private MediaSource buildMediaSource(Uri uri) {
return new ExtractorMediaSource.Factory(
new DefaultHttpDataSourceFactory("exoplayer-codelab")).
createMediaSource(uri);
}
#Override
public void onStart() {
super.onStart();
if (Util.SDK_INT > 23) {
if (player == null) {
initializePlayer();
}
}
}
#Override
public void onResume() {
super.onResume();
if ((Util.SDK_INT <= 23 || player == null)) {
initializePlayer();
}
}
#Override
public void onPause() {
super.onPause();
if (Util.SDK_INT <= 23) {
releasePlayer();
}
}
#Override
public void onStop() {
super.onStop();
if (Util.SDK_INT > 23) {
releasePlayer();
}
}
private void releasePlayer() {
if (player != null) {
player.release();
player = null;
}
}
}
and the XML file to go with it.... The zoomable declaration is "on" right now but the code can easily use either the non-zoomable one or the PlayerView (by changing the type and not attaching the texture); that one works perfectly well, including properly handling rotation.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/root"
android:focusable="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true">
<TextureView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:id="#+id/video_view3" />
<ua.polohalo.zoomabletextureview.ZoomableTextureView
android:id="#+id/video_view2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
app:maxScale="4"/>
<com.google.android.exoplayer2.ui.PlayerView
android:id="#+id/video_view"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:use_controller="false"/>
</FrameLayout>
Update: After much head-banging the following code works EXCEPT if you try to use it in a fragment, in which case the TextView extension has problems due to how minimum and maximum scale values get picked up. The obvious "hack" answer is to check for minScale = 0 and force it to 1.0 if you find it un-initialized.
Hope this helps someone else out.
package net.cudasystems.android.videotest;
import android.net.Uri;
import android.os.Bundle;
import android.support.constraint.ConstraintLayout;
import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
import android.view.TextureView;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.DefaultRenderersFactory;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
import com.google.android.exoplayer2.util.Util;
public class MainActivity extends AppCompatActivity {
private String mURL = "http://set-to-an-mp4-URL"
TextureView mPlayerView;
SimpleExoPlayer player = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPlayerView = findViewById(R.id.video_view);
}
private void initializePlayer() {
DefaultRenderersFactory renderersFactory =
new DefaultRenderersFactory(this, DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON);
player = ExoPlayerFactory.newSimpleInstance(
renderersFactory,
new DefaultTrackSelector(), new DefaultLoadControl());
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
// Make sure the initial aspect ratio is 16:9 (otherwise a TextureView init's to the LARGER of
// the two dimensions of the video irrespective of the orientation setting and screws the aspect ratio!)
int width = metrics.widthPixels;
int newHeight = (width * 9) / 16;
mPlayerView.setLayoutParams(new ConstraintLayout.LayoutParams(width, newHeight));
mPlayerView.invalidate();
player.setVideoTextureView(mPlayerView);
player.setPlayWhenReady(true);
Uri uri = Uri.parse(mURL);
MediaSource mediaSource = buildMediaSource(uri);
player.prepare(mediaSource, true, true);
}
private MediaSource buildMediaSource(Uri uri) {
return new ExtractorMediaSource.Factory(
new DefaultHttpDataSourceFactory("exoplayer-codelab")).
createMediaSource(uri);
}
#Override
public void onStart() {
super.onStart();
if (Util.SDK_INT > 23) {
if (player == null) {
initializePlayer();
}
}
}
#Override
public void onResume() {
super.onResume();
if ((Util.SDK_INT <= 23 || player == null)) {
initializePlayer();
}
}
#Override
public void onPause() {
super.onPause();
if (Util.SDK_INT <= 23) {
releasePlayer();
}
}
#Override
public void onStop() {
super.onStop();
if (Util.SDK_INT > 23) {
releasePlayer();
}
}
private void releasePlayer() {
if (player != null) {
player.release();
player = null;
}
}
}
And the working XML to go with it:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/root"
android:focusable="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:keepScreenOn="true">
<ua.polohalo.zoomabletextureview.ZoomableTextureView
android:id="#+id/video_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
app:maxScale="4"
app:minScale="1"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Does This work?"
android:textColor="#android:color/holo_red_dark"
app:layout_constraintBottom_toBottomOf="parent" />
</android.support.constraint.ConstraintLayout>

Android: Selecting an Image from sdcard and displaying it in Fragment

I'm working with fragments (API 4.1) and I want to let the user press a button, access his/her gallery, select an image, and have that image display an imageview on the original fragment where the button appeared. I'm using the following code:
public class FillBox1Frag extends Fragment {
Button addPics, placeBox;
ImageView imgView;
Bitmap b;
Uri photoUri;
LinearLayout fillBoxLayout;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
if (container == null) {
return null;
}
fillBoxLayout = (LinearLayout) inflater.inflate(R.layout.fillbox1_frag,
container, false);
newBin = new Bin();
addPics = (Button) fillBoxLayout.findViewById(R.id.bPics);
imgView = (ImageView) fillBoxLayout.findViewById(R.id.imageView1);
addPics.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Intent picChooser = new Intent(Intent.ACTION_GET_CONTENT,
MediaStore.Images.Media.INTERNAL_CONTENT_URI);
picChooser.setType("image/*");
startActivityForResult(picChooser, 12345);
}
});
return fillBoxLayout;
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case 12345:
if (resultCode == 12345) {
photoUri = data.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = FillBox1Frag.this.getActivity()
.getContentResolver()
.query(photoUri, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String filePath = cursor.getString(columnIndex);
cursor.close();
b = BitmapFactory.decodeFile(filePath);
imgView.setImageBitmap(b);
}
}
}
I access the Gallery, but upon selection, it just returns to the original fragment and doesn't display the image. Here's my XML:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fillbox"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:tag="fillbox" >
<Button
android:id="#+id/bPics"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="89dp"
android:background="#drawable/buttonpics" />
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
I've found plenty of answers dealing with a similar question, but nothing that has been able to help me with how to create this process using fragments. Any ideas on how to get my selected image to appear in the ImageView? Thanks for the help!

ListView with custom view as item only shows one element

I have an AlertDialog that I inflate from this layout:
<?xml version="1.0" encoding="utf-8"?>
<ListView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/List"
android:layout_alignParentTop="true"
android:layout_width="match_parent"
android:layout_height="400dp"/>
I need every item of the list to be a view described by this
xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#20f0f0f0"
android:orientation="horizontal" >
<CheckBox
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:id="#+id/cb_persistent"/>
<TextView
style="#style/Label"
android:layout_gravity="center_vertical"
android:gravity="center_horizontal|center_vertical"
android:layout_width="fill_parent"
android:layout_height="#dimen/button_height"
android:layout_toLeftOf="#+id/btn_connect"
android:layout_toRightOf="#+id/cb_persistent"
android:id="#+id/lbl_name_address"/>
<Button
android:layout_gravity="center_vertical"
style="#style/Button.Plain"
android:layout_width="wrap_content"
android:layout_alignParentRight="true"
android:id="#+id/btn_connect"
android:text="#string/Connect"/>
</RelativeLayout>
And this is the adapter I'm trying to use for it. I've also tried implementing ListAdapter, result was the same: only 1 list row is showing, the dialog is exactly 1 row high. With this adapter it's the last row, with ListAdapter - the first. What am I doing wrong?
private class ListItem extends View {
public ListItem(Context context) {
super(context);
View content = ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.list_element, null);
setView(content);
m_cbPersistent = (CheckBox) content.findViewById(R.id.cb_persistent);
m_btnConnect = (Button) content.findViewById(R.id.btn_connect);
m_lblName = (TextView) content.findViewById(R.id.lbl_name_address);
}
public CheckBox m_cbPersistent = null;
public Button m_btnConnect = null;
public TextView m_lblName = null;
}
class NewAdapter extends ArrayAdapter<ListItem>
{
public NewAdapter(Context context) {
super(context, 0);
m_context = context;
}
#Override
public int getCount() {
return m_items.size();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (position < getCount())
return m_items.elementAt(position);
else
return null;
}
void addNewItem ()
{
m_items.add(new NetworkCameraEntry(m_context));
}
void removeItem (int index)
{
if (index < getCount())
{
m_items.remove(index);
}
}
#Override
public boolean isEmpty() {
return m_items.size() <= 0;
}
#Override
public boolean areAllItemsEnabled() {
return true;
}
#Override
public boolean isEnabled(int position) {
return true;
}
private Context m_context = null;
private Vector<ListItem> m_items = new Vector<ListItem>();
}
This is how I initialize it in the AlertDialog's constructor:
public class MyDialog extends AlertDialog {
public MyDialog(Context context) {
super(context, 0);
View content = ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.network_cameras_list_window, null);
setView(content);
m_adapter = new NewAdapter(context);
m_list = (ListView) content.findViewById(R.id.List);
m_list.setAdapter(m_adapter);
m_adapter.addNewItem();
m_adapter.addNewItem();
}
private ListView m_list = null;
private NewAdapter m_adapter = null;
}
m_items.size is 1 when the adapter is constructed and gets populated over time.
m_items.size is cached so you have to invalidate the adapter on each m_items.add
Yet this is not the way to go. A better option is to get your data populated before constructing the adapter and pass is to the adapter. Any altering of the data you have to notify / invalidate the adapter with
notifyDataSetInvalidated();
notifyDataSetChanged();

How to add a widget to a ListView to scroll with items, but also be visible when the ListView's adapter is empty

I have a ListView and a widget. I want the widget to be always on the top of ListView, and it should be able to scroll with the items but when there is no items in adapter it should still be visible. This is how it doesn't scroll:
The layout file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<Button
android:id="#+id/btn_togle_empty"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="toggle empty"
/>
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1">
<ListView
android:id="#+id/list_test"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
<ViewStub
android:id="#+id/empty_layout"
android:layout="#layout/empty"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</FrameLayout>
</LinearLayout>
The code for the activity:
public class MyActivity extends Activity {
private MyAdapter adapter;
private ListView v;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
v = (ListView) findViewById(R.id.list_test);
View empty = findViewById(R.id.empty_layout);
v.setEmptyView(empty);
final MyAdapter adapter = new MyAdapter();
v.setAdapter(adapter);
Button btn = (Button) findViewById(R.id.btn_togle_empty);
btn.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
adapter.togleEmpty();
}
});
}
private class MyAdapter extends BaseAdapter {
boolean empty = false;
#Override
public int getCount() {
return empty ? 0 : 50;
}
#Override
public Object getItem(int i) {
return new Object();
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
TextView v = new TextView(MyActivity.this);
v.setText("STRING");
return v;
}
public void togleEmpty() {
empty = !empty;
notifyDataSetChanged();
}
}
}
I had one more idea, add the widget as header, but it disappears when the ListView is empty. How can I achieve the result I want?
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
if (i == 0) { return custom_widget_view; }
}

How to Show Different Layouts inside Fragments

I am working with two fragments in Android Honeycomb (Tab). In the left is a ListView and in the right is a preview of the item selected from the list. When one of the buttons is clicked, I want to show different layouts on the left. How is it possible?
Thanks in advance.
You can do this, I made the same thing with use of these links, here is my code which I am sharing with you in the hope that it will be helpful for you... You will first have to create 4 layouts. 2 of which will be for landscape mode, one for portrait mode and another for tablets. You have to create a couple more folders for layouts and their name should be like layout-xlarge and layout-xlarge-port, this way you can create fragments for both mobile devices and tablets.
MasterFragment Activity:
public class MasterFragment extends ListFragment {
Boolean isDualPane;
int position;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ArrayList<String> parkNames = new ArrayList<String>();
for (Park park : Resort.PARKS) {
parkNames.add(park.getName());
}
setListAdapter(new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, parkNames));
View detailFrame = getActivity().findViewById(R.id.detail);
isDualPane = detailFrame != null && detailFrame.getVisibility() == View.VISIBLE;
if (savedInstanceState != null) {
position = savedInstanceState.getInt("position", 0);
}
if (isDualPane) {
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
showDetail(position);
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("position", position);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
showDetail(position);
}
void showDetail(int position) {
this.position = position;
if (isDualPane) {
getListView().setItemChecked(position, true);
DetailFragment detailFragment = (DetailFragment) getFragmentManager()
.findFragmentById(R.id.detail);
if (detailFragment == null || detailFragment.getIndex() != position) {
detailFragment = new DetailFragment(position);
FragmentTransaction ft = getFragmentManager()
.beginTransaction();
ft.replace(R.id.detail, detailFragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
}
} else {
Intent intent = new Intent();
intent.setClass(getActivity(), DetailActivity.class);
intent.putExtra("position", position);
startActivity(intent);
}
}
}
Second Activity - DetailFragment Activity:
public class DetailActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.detail_act);
Bundle bundle = getIntent().getExtras();
int position = bundle.getInt("position");
System.out.println("RR : position is : " + position);
Integer[] images = { R.drawable.pic1, R.drawable.pic2, R.drawable.pic3,
R.drawable.pic4, R.drawable.pic5, R.drawable.pic6,
R.drawable.pic7, R.drawable.pic8, R.drawable.pic9,
R.drawable.pic10, R.drawable.pic11, R.drawable.pic12,
R.drawable.pic13 };
final ImageView imgview = (ImageView) findViewById(R.id.imageView1);
imgview.setImageResource(images[position]);
// DetailFragment detailFragment = new DetailFragment(position);
// FragmentManager fm = getSupportFragmentManager();
// FragmentTransaction ft =fm.beginTransaction();
// ft.add(android.R.id.content, detailFragment).commit();
}
}
Now you have to create a third activity, MasterGridActivity for my images which I am using for showing in fragment in GridView.
public class MasterGridActivity extends Fragment {
Boolean isDualPane;
GridView gridView;
ListView listView;
int position;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.gridview, container, false);
gridView = (GridView) view.findViewById(R.id.gridViewImage);
gridView.setAdapter(new MyAdapter(view.getContext()));
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
View detailFrame = getActivity().findViewById(R.id.detail);
isDualPane = detailFrame != null && detailFrame.getVisibility() == View.VISIBLE;
gridView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
if (!isDualPane) {
Intent intent = new Intent();
intent.setClass(getActivity(), DetailActivity.class);
intent.putExtra("position", pos);
startActivity(intent);
} else {
DetailFragment detailFragment = (DetailFragment) getFragmentManager().findFragmentById(R.id.detail);
if (detailFragment == null || detailFragment.getIndex() != pos) {
detailFragment = new DetailFragment(pos);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.detail, detailFragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
}
}
}
});
super.onActivityCreated(savedInstanceState);
}
}
Now here is my image adapter - MyAdapter - for my images which extends a BaseAdapter.
public class MyAdapter extends BaseAdapter {
private Context mContext;
public MyAdapter(Context c) {
mContext = c;
}
#Override
public int getCount() {
return mThumbIds.length;
}
#Override
public Object getItem(int arg0) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) { // if it's not recycled, initialize some attributes
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(100, 100));
imageView.setImageResource(mThumbIds[position]);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(0, 0, 0, 0);
} else {
imageView = (ImageView) convertView;
}
imageView.setImageResource(mThumbIds[position]);
return imageView;
}
static Integer[] mThumbIds = { R.drawable.pic1, R.drawable.pic2,
R.drawable.pic3, R.drawable.pic4, R.drawable.pic5, R.drawable.pic6,
R.drawable.pic7, R.drawable.pic8, R.drawable.pic9,
R.drawable.pic10, R.drawable.pic11, R.drawable.pic12,
R.drawable.pic13,
};
}
Now I am sharing the XML files for these fragments.
Main.xml
<?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="horizontal">
<fragment
android:id="#+id/master"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="org.fragment.MasterGridActivity" />
</LinearLayout>
gridview.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" >
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gridViewImage"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:numColumns="auto_fit"
android:columnWidth="90dp"
android:horizontalSpacing="10dp"
android:verticalSpacing="10dp"
android:gravity="center"
android:stretchMode="columnWidth" />
</LinearLayout>
detail_fragment.xml: This XML is for showing the detail in another fragment.
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="8dp" />
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="8dp" />
</LinearLayout>
</ScrollView>
detail_act.xml
<?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" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="#drawable/ic_launcher" />
</LinearLayout>
Make the same XML for landscape mode and for tablets. It's working fine for me. Hope it will helpful for you.
You need to define an event callback to the activity activity callback. That is, your left fragment must first notify the container activity that an event occurred (i.e. one of the list items were selected). The container activity will then pass this information to the right fragment, which will then update its UI accordingly.
I could explain this in more detail, but there are several tutorials on the internet that teach just that. I suggest you read through some of them, as the concept will make a lot more sense once you do.

Resources