33193


以下のコードは、Android Developersサイトに掲載されているもので、ビューのタッチを認識する範囲を大きくする処理です。  
自身のプロジェクトに貼り付け、想定の動きをすることを確認できたのですが、この処理を関数化したいと考えています。  
parentView、myButtonの部分を引数にして渡す関数にしてみたのですが、「variable is accessed from within
inner class, needs to be declared final」とエラー表示が出るのですが、どうのように修正すればよいかが分かりません。

どのように記述すれば、素敵な関数にできるでしょうか？

<https://developer.android.com/training/gestures/viewgroup.html#delegate>

[code]

    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            // Get the parent view
            View parentView = findViewById(R.id.parent_layout);
    
            parentView.post(new Runnable() {
                // Post in the parent's message queue to make sure the parent
                // lays out its children before you call getHitRect()
                @Override
                public void run() {
                    // The bounds for the delegate view (an ImageButton
                    // in this example)
                    Rect delegateArea = new Rect();
                    ImageButton myButton = (ImageButton) findViewById(R.id.button);
                    myButton.setEnabled(true);
                    myButton.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            Toast.makeText(MainActivity.this,
                                    "Touch occurred within ImageButton touch region.",
                                    Toast.LENGTH_SHORT).show();
                        }
                    });
    
                    // The hit rectangle for the ImageButton
                    myButton.getHitRect(delegateArea);
    
                    // Extend the touch area of the ImageButton beyond its bounds
                    // on the right and bottom.
                    delegateArea.right += 100;
                    delegateArea.bottom += 100;
    
                    // Instantiate a TouchDelegate.
                    // "delegateArea" is the bounds in local coordinates of
                    // the containing view to be mapped to the delegate view.
                    // "myButton" is the child view that should receive motion
                    // events.
                    TouchDelegate touchDelegate = new TouchDelegate(delegateArea,
                            myButton);
    
                    // Sets the TouchDelegate on the parent view, such that touches
                    // within the touch delegate bounds are routed to the child.
                    if (View.class.isInstance(myButton.getParent())) {
                        ((View) myButton.getParent()).setTouchDelegate(touchDelegate);
                    }
                }
            });
        }
    }
    
[/code]


CC BY-SA 3.0
2017-03-08T12:59:59.087
33192
2017-03-08T14:38:57.700
question
android java
タッチを認識するエリアを広げる処理を関数化したい


質問の中でエラー文だけ書かれても、どういうコードを書いてエラーが出たのかが分からないのでなんとも答えにくいのですが、多分こういうコードを書いたんじゃないかなと推測します。

[code]

    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            // Get the parent view
            View parentView = findViewById(R.id.parent_layout);
            ImageButton myButton = (ImageButton) findViewById(R.id.button);
            // メソッド呼び出し
            touchDelegate(parentView, myButton);
        }
    
        public void touchDelegate(View parentView, ImageButton myButton){
            parentView.post(new Runnable() {
                @Override
                public void run() {
                    Rect delegateArea = new Rect();
                    // この辺でエラー
                    myButton.setEnabled(true);
                    myButton.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            Toast.makeText(MainActivity.this,
                                    "Touch occurred within ImageButton touch region.",
                                    Toast.LENGTH_SHORT).show();
                        }
                    });
    
                    myButton.getHitRect(delegateArea);
    
                    delegateArea.right += 100;
                    delegateArea.bottom += 100;
    
                    TouchDelegate touchDelegate = new TouchDelegate(delegateArea,
                            myButton);
    
                    if (View.class.isInstance(myButton.getParent())) {
                        ((View) myButton.getParent()).setTouchDelegate(touchDelegate);
                    }
                }
            });
        }
    }
    
[/code]

このときに質問内容のエラー「variable is accessed from within inner class, needs to be
declared final」と出たのだとしたら、メソッド内で使用しているmyButtonのところじゃないかなと思います。

[code]

    parentView.post(new Runnable(){
        @Override
        public void run(){
            myButton.~~; // <- ここ
        }
    });
    
[/code]

これは、メソッドの引数であるmyButtonがfinal修飾子が付いていないのにインナークラス内で使用されようとしているときに起こるコンパイルエラー、つまり文法ミスです。(Javaの文法を勉強しましょう)  
このエラーの回避方法は単純で、引数にfinalを付けるだけです。

[code]

        // ImageButtonの前にfinalを付ける
        public void touchDelegate(View parentView, final ImageButton myButton){
            parentView.post(new Runnable() {
                @Override
                public void run() {
    
[/code]

どうしてfinalがついてないといけないのか……などは、ググれば一発で出てくると思うので、色々と調べてみるといいんじゃないんでしょうか。(「Java
インナークラス final」とか)  
ちなみに、このエラー文をそのままGoogleの検索ボックスに入れて検索すると、たくさん答えが出てくるので、それも参考にしてみればいいんじゃないでしょうか。


CC BY-SA 3.0
2017-03-08T14:38:57.700
33193
2017-03-08T14:38:57.700
7655
33192
answer