2

I am woking on a project that uses drag and drop views within a relative layout. I have a button that generates a new image view when clicked. This image view is created in the top left corner of the screen, (0,0) relative to the parent view. I can then drag and drop the image view anywhere I want. Here's the problem: When I click the button again to make another image view, all of the image views move to the top left corner. Is Is there a different add method I should use or some way to keep the other image views in place? All the code is posted below.

Code:

MyFragment.java

package com.example.layouttest;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class MyFragment extends Fragment {
    public static final String EXTRA_MESSAGE = "EXTRA_MESSAGE";
    public String text;
    static FragmentManager fragMan;

    public static final MyFragment newInstance(String message)
    {
        MyFragment f = new MyFragment();
        f.setRetainInstance(true);
        Bundle bdl = new Bundle(1);
        bdl.putString(EXTRA_MESSAGE, message);
        f.setArguments(bdl);
        return f;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
        Bundle savedInstanceState) {
        String message = getArguments().getString(EXTRA_MESSAGE);
        View v = inflater.inflate(R.layout.myfragment_layout, container, false);
        TextView messageTextView = (TextView)v.findViewById(R.id.textView);
        messageTextView.setText(message);
        text = message;
        return v;
    }
}

PageViewActivity.java

package com.example.layouttest;

import java.util.ArrayList;
import java.util.List;

import com.example.layouttest.R;

import android.content.ClipData;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.DragShadowBuilder;
import android.view.View.OnTouchListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.RelativeLayout;

public class PageViewActivity extends FragmentActivity {
    MyPageAdapter pageAdapter;
    FragmentManager fragMan;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_page_view);
        fragMan = getSupportFragmentManager();
        List<Fragment> fragments = getFragments();
        FragmentTransaction fragTrans = fragMan.beginTransaction();
        fragTrans.commit();
        pageAdapter = new MyPageAdapter(getSupportFragmentManager(), fragments);
        ViewPager pager = (ViewPager)findViewById(R.id.viewpager);
        pager.setAdapter(pageAdapter);
        pager.setPageTransformer(true, new ZoomOutPageTransformer());
        pager.setCurrentItem(pageAdapter.cur);
    }

    public void click(View v){
        RelativeLayout layout = (RelativeLayout)v.getParent();
        ImageView image = new ImageView(this);
        image.setLayoutParams(new LayoutParams(80,80));
        image.setImageDrawable(getResources().getDrawable(R.drawable.shape));
        image.setOnTouchListener(new MyTouchListener());
        layout.setOnDragListener(new MyDragListener(layout));
        layout.addView(image);
    }

    private List<Fragment> getFragments(){
        List<Fragment> fList = new ArrayList<Fragment>();
        for(int i = 1; i <= 5;i++){
            MyFragment f = MyFragment.newInstance("Fragment " + i);
            fList.add(f);
        }
        return fList;
    }

    private class MyPageAdapter extends FragmentPagerAdapter {
        public List<Fragment> fragments;
        public int cur;

        public MyPageAdapter(FragmentManager fm, List<Fragment> fragments) {
            super(fm);
            this.fragments = fragments;
            cur = fragments.size()/2;
        }
        @Override
        public Fragment getItem(int position) {
            return this.fragments.get(position);
        }

        @Override
        public int getCount() {
            return this.fragments.size();
        }
    }

    private class MyTouchListener implements OnTouchListener{

        @Override
        public boolean onTouch(View arg0, MotionEvent arg1) {
            if(arg1.getAction() == MotionEvent.ACTION_DOWN){
                ClipData data = ClipData.newPlainText("", "");
                DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(arg0);
                arg0.startDrag(data, shadowBuilder, arg0, 0);
                arg0.setVisibility(View.INVISIBLE);
            }
            return true;
        }
    }
}

MyDragListener.java

package com.example.layouttest;

import android.util.Log;
import android.view.DragEvent;
import android.view.View;
import android.view.View.OnDragListener;
import android.widget.RelativeLayout;

public class MyDragListener implements OnDragListener{
    int x;
    int y;
    RelativeLayout layout;

    public MyDragListener(RelativeLayout l){
        layout = l;
    }

    @Override
    public boolean onDrag(View v, DragEvent event) {
        int action = event.getAction();
        View view = (View) event.getLocalState();
        RelativeLayout l = (RelativeLayout)view.getParent();
        if(!l.equals(layout))
            return false;
        if(action == DragEvent.ACTION_DRAG_LOCATION){
            x = (int)event.getX();
            y = (int)event.getY();
            Log.d("DRAG", x + "," + y);
        }
        if(action == DragEvent.ACTION_DRAG_ENDED){
            Log.d("DRAG", "Dropped at " + x + "," + y);
            view.layout(x-(view.getWidth()/2), y-(view.getHeight()/2), x+(view.getWidth()/2), y+(view.getHeight()/2));
            view.setVisibility(View.VISIBLE);
        }
        return true;
    }
}

ZoomOutPageTransformer.java

package com.example.layouttest;

import android.support.v4.view.ViewPager.PageTransformer;
import android.view.View;

public class ZoomOutPageTransformer implements PageTransformer {
    private static float MIN_SCALE = 0.85f;
    private static float MIN_ALPHA = 0.5f;

    public void transformPage(View view, float position) {
        int pageWidth = view.getWidth();
        int pageHeight = view.getHeight();

        if (position < -1) { // [-Infinity,-1)
            // This page is way off-screen to the left.
            view.setAlpha(0);

        } else if (position <= 1) { // [-1,1]
            // Modify the default slide transition to shrink the page as well
            float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
            float vertMargin = pageHeight * (1 - scaleFactor) / 2;
            float horzMargin = pageWidth * (1 - scaleFactor) / 2;
            if (position < 0) {
                view.setTranslationX(horzMargin - vertMargin / 2);
            } else {
                view.setTranslationX(-horzMargin + vertMargin / 2);
            }

            // Scale the page down (between MIN_SCALE and 1)
            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);

            // Fade the page relative to its size.
            view.setAlpha(MIN_ALPHA +
                    (scaleFactor - MIN_SCALE) /
                    (1 - MIN_SCALE) * (1 - MIN_ALPHA));

        } else { // (1,+Infinity]
            // This page is way off-screen to the right.
            view.setAlpha(0);
        }
    }
}

myfragment_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:id="@+id/layout"
    android:background="#00308F" >

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="20dp"
        android:onClick="click"
        android:text="@string/hello_world" />

</RelativeLayout>

shape.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" 
    android:shape="rectangle">

    <stroke 
        android:width="2dp"
        android:color="#FFFFFF" />
    <gradient 
        android:angle="225"
        android:endColor="#FFFFFF"
        android:startColor="#000000" />
    <corners 
        android:bottomLeftRadius="7dp"
        android:bottomRightRadius="7dp"
        android:topLeftRadius="7dp"
        android:topRightRadius="7dp" />

</shape>

activity_page_view.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" >

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

</RelativeLayout>

I would be greatly appreciative if anyone can find the flaw in my code or let me know how to keep my images in place when adding a new one.

Here is a link for the .apk if anyone would like to see the problem firsthand: LayoutTest.apk

4

1 回答 1

5

Problem solved.

Where I had

view.layout(x-(view.getWidth()/2), y-(view.getHeight()/2), x+(view.getWidth()/2), y+(view.getHeight()/2));

I needed to have

view.setX(x-(view.getWidth()/2));
view.setY(y-(view.getHeight()/2));

Apparently, .layout() is a relative positioning that depends on the view hierarchy, whereas .setX() and .setY() are absolute positioning that are independent of the hierarchy. When a new view is added to the layout, the hierarchy changes and anything that is affected goes back to it's default starting position. For xml added views, the default position is defined, but for programmatically added views, the default position is (0,0).

All I had to do to fix the issue was replace the line with the two new ones and everything works fine!

于 2013-06-07T18:44:13.997 回答