拖放持久位置

时间:2013-06-07 18:00:27

标签: android android-fragments drag-and-drop android-relativelayout

我正在讨论一个在相对布局中使用拖放视图的项目。我有一个按钮,单击时会生成一个新的图像视图。此图像视图在屏幕的左上角创建,(0,0)相对于父视图。然后我可以将图像视图拖放到我想要的任何地方。问题在于:当我再次单击该按钮以创建另一个图像视图时,所有图像视图都会移动到左上角。是否有一种不同的添加方法我应该使用或某种方式来保持其他图像视图到位?所有代码都发布在下面。

代码:

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>

如果有人能够找到我的代码中的缺陷或让我知道如何在添加新代码时保留我的图像,我将非常感激。

以下是.apk的链接,如果有人想直接看到问题:LayoutTest.apk

1 个答案:

答案 0 :(得分:5)

问题解决了。

我在哪里

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

我需要

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

显然,.layout()是相对定位,取决于视图层次结构,而.setX().setY()是绝对定位,独立于层次结构。将新视图添加到布局时,层次结构会更改,受影响的任何内容都会返回到其默认的起始位置。对于xml添加的视图,定义了默认位置,但对于以编程方式添加的视图,默认位置为(0,0)。

我需要做的就是解决这个问题,用两个新的替换线路,一切正常!